圖7再返回首頁 再按右上角ˆ Account'連結’會發現畫面直接跳至個人資眀畫面 箱实①我的易要)工具①明 中上一·+·图②、我的鼎守媒④三日 剩址 ht Localhost sbrettomerd JavaTM Pet store 2EE BluePrints Sample Application Account I CartI Pets Your Account Information My List Rinds Contact Information Street Address 1234 Anywhere Street City Palo Ato E-Mail aaaobbbccc Credit Card Information 内肝路 圖8個人資訊畫面 請注意圖4 Petstore首頁畫面左下角出現的 Urlhttp:/localhost8080/petstore/customer.do,它其實就是圖6個人資訊畫面, 但系統並沒有直接從圖4跳至圖6·而先換成圖5登入畫面’要求我們做登人動 作·輸入帳號及密碼’驗證成功後扌跳至圖6;若是再次從首頁進λ個人資訉 系統並不會再次要求登λ·在這裡有兩個重點要提 l. SignOnFilter:若使用者進廴的頁面是受到保護的則系統會先將畫面轉至登入 畫面,要求登入 2. customer do:它代表的是一個動作加一個畫面的組合·以本例來說·從資料庫 讀取個人資訊’組成完整HIML畫面顯示。 Sign on filter 筆者將使用者進入使用者基本資料瀏覽畫面的流程分爲三個階段 1使用者欲進廴使用者基本資料瀏覽畫面 (customer. do)’因未登入過’被 SignOnFilter攔截·轉至登入畫面( Signon. screen) 2使用者輸廴帳號及密碼按ˆ sumit'後’再度由 SignOnFilter攔截 SignOnFilter 亦負責帳號丶密碼檢核工作ν確認無誤後·則將網頁轉導( forward至第一階段
圖 7 再返回首頁 再按右上角”Account”連結,會發現畫面直接跳至個人資訊畫面: 圖 8 個人資訊畫面 請注意圖 4 Petstore 首頁畫面左下角出現的 URL:http://localhost:8080/petstore/customer.do,它其實就是圖 6 個人資訊畫面, 但系統並沒有直接從圖 4 跳至圖 6,而先換成圖 5 登入畫面,要求我們做登入動 作,輸入帳號及密碼,驗證成功後才跳至圖 6;若是再次從首頁進入個人資訊, 系統並不會再次要求登入,在這裡有兩個重點要提: 1.SignOnFilter:若使用者進入的頁面是受到保護的,則系統會先將畫面轉至登入 畫面,要求登入。 2.customer.do:它代表的是一個動作加一個畫面的組合,以本例來說,從資料庫 讀取個人資訊,組成完整 HTML 畫面顯示。 SignOnFilter 筆者將使用者進入使用者基本資料瀏覽畫面的流程分為三個階段: 1.使用者欲進入使用者基本資料瀏覽畫面(customer.do),因未登入過,被 SignOnFilter 攔截,轉至登入畫面(signon.screen)。 2.使用者輸入帳號及密碼按”sumit”後,再度由 SignOnFilter 攔截,SignOnFilter 亦負責帳號、密碼檢核工作,確認無誤後,則將網頁轉導(forward)至第一階段
使用者欲進入之使用者基本資料瀏覽畫面( customer do 3重覆第一階段動作· SignOn Filter檢査使用者已登λ過’放行轉導至使用者基 本資料瀏覽畫面( customer do)。 第一階段 欲觀察 Servlet Filter·先要了解它的影響範圍’請開啓 deploytool(註2)’滑 鼠點選 Petstore WAR’選擇右邊 Filter Mapping頁·會發現此 Filter的影響範圍是 所有網頁 口 Applications iter Maping JNDI Names Resource Emw Refs Resource Rets Security Roles Human Resourtaclient nf Hiter Mappin一 Filter Nam Target Type URL Pattern URL Patten 0-8 PetstoreJAR PdGpnerator. MAR o MultiAppserverRequester 0- Eib cessingCener EAR Edit Filter List ◆ SarmpleRepyBeanApr 令8upgr 圖9 Filter影響範圍 也可在 web. xml看到設定’請參考前面敘迒’接下來請開啓 SignOnFilter. java 它的原始碼位置在 Petstore homelsrc\components\signon\src\com\sun j2eelblueprintslsignonlweb\SignO fIlter. java 先看 SignOnFilter初始動作,約在87列 public void init( Filter Config config) throws Servlet Exception i URL protectedResourcesURL=null
使用者欲進入之使用者基本資料瀏覽畫面(customer.do)。 3.重覆第一階段動作,SignOnFilter 檢查使用者已登入過,放行轉導至使用者基 本資料瀏覽畫面(customer.do)。 第一階段 欲觀察 Servlet Filter,先要了解它的影響範圍,請開啟 deploytool(註 2),滑 鼠點選 PetstoreWAR,選擇右邊 Filter Mapping 頁,會發現此 Filter 的影響範圍是 所有網頁。 圖 9 Filter 影響範圍 也可在 web.xml 看到設定,請參考前面敘述,接下來請開啟 SignOnFilter.java, 它的原始碼位置在 Petstore_home\src\components\signon\src\com\sun\j2ee\blueprints\signon\web\SignO nFilter.java。 先看 SignOnFilter 初始動作,約在 87 列: public void init(FilterConfig config) throws ServletException { this.config = config; URL protectedResourcesURL = null; try {
/讀取 Signon- config. xml tected ResourceSURL config getServletContext( getResource("/WEB-INF/signon-configxml"); SignOndAO dao=new SignOnDAO(protectedResourcesURL) /散取登入失敗查面( signon errorscreen) signOn ErrorPage-dao getSignOnErrorPageO /取登入登面( Signon screen) signOnPage =dao. getSignOnPageO /取所有欲保護登面,組成 HashMap protectedResources=dao. getProtectedResourceso i catch (java. net. MalformedURLException ex)i System. err println("Signon Filter: malformed URL exception: ex); 它在初始化時會先讀取 Petstore home\\appslpetstorelsrcldocroot\ WEB-INF\signon-config xml iILKaEX Data Access Object(DAO)’以方便後續程式存取(註3)·此xml檔案主要功用記 錄登入畫面丶登入失敗畫面及所有需登入扌能使用的畫面之URL,以下是 Signon- config. xml片段 <signon-config !- Form sign on page(登入量面-> <signon-form-login-page> Signon screen </signon-form-login-page> <!- Error page when sign on fails(登入失敗查面-> <signon-form-error-page> signon error, screen </signon-form-error-page <I-A Protected Resource-> <web-resource-collection> <web-resource-name>Customer Screen</web-resource-name> <url-pattern>customer screen</url-pattern> web-resource-collection> ecurity-constraint>
//謮取 signon-config.xml protectedResourcesURL = config.getServletContext().getResource("/WEB-INF/signon-config.xml"); SignOnDAO dao = new SignOnDAO(protectedResourcesURL); //讀取登入失敗畫面(signon_error.screen) signOnErrorPage = dao.getSignOnErrorPage(); //讀取登入畫面(signon.screen) signOnPage = dao.getSignOnPage(); //讀取所有欲保護畫面,組成 HashMap protectedResources = dao.getProtectedResources(); } catch (java.net.MalformedURLException ex) { System.err.println("SignonFilter: malformed URL exception: " + ex); } } 它在初始化時會先讀取 Petstore_home\src\apps\petstore\src\docroot\WEB-INF\signon-config.xml,並組成 Data Access Object(DAO),以方便後續程式存取(註 3),此 xml 檔案主要功用記 錄登入畫面、登入失敗畫面及所有需登入才能使用的畫面之 URL,以下是 signon-config.xml 片段: <signon-config> <!-- Form Sign On Page(登入畫面)--> <signon-form-login-page> signon.screen </signon-form-login-page> <!-- Error Page When Sign On fails(登入失敗畫面)--> <signon-form-error-page> signon_error.screen </signon-form-error-page> <!-- A Protected Resource--> <security-constraint> <web-resource-collection> <web-resource-name>Customer Screen</web-resource-name> <url-pattern>customer.screen</url-pattern> </web-resource-collection> </security-constraint>
<!- A Protected resource本例之保護查面)-> <security-constraint> <web-resource-collection> <web-resource-name>Customer Action</web-resource-name> do</url-pattern> /web-resource-collection> </security-constraint> 接著請看 SignOnFilter實際運作的主要函式 do Filter·約在107列 public void doFilter( Servlet Request request, ServletResponse response Filter Chain chain) throws IOException, Servlet Exception i Httpservletr I-(httpservLetRequestor String currentURI- hreq getRequestURLO. toString (; String currentURL= hreq getRequestURIO; ∥ get everything after int firstSlash=currentURL. indexof("/", 1); // jump past the starting slash String targetURL =null; 取得使用者欲前往之URL·以本例來說·即是 customer do if (first Slash I =-1)targetURL= currentURL substring( firstSlash+ 1 urrentURL. length) 判斷使用者從登入董面( Signon. screen)進行驗證工作 if( targetURL !=null)&& targetURL equals(FORM SIGNON URL))( alidate SignOn( request, response, chain) //jump out of this method return: // check if the user is signed on 檢查使用者是否登入過,從 Session取出登入標記,作判斷之用 boolean signedOn= false if(hreq get Session(). getAttribute(SIGNED ON USER)I=null)( signedOn = Boolean hreq getSession( get Attribute(SIGNED ON USER). boolean value i else i
<!-- A Protected Resource(本例之保護畫面)--> <security-constraint> <web-resource-collection> <web-resource-name>Customer Action</web-resource-name> <url-pattern>customer.do</url-pattern> </web-resource-collection> </security-constraint> 接著請看 SignOnFilter 實際運作的主要函式 doFilter(),約在 107 列: public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest hreq = (HttpServletRequest)request; String currentURI = hreq.getRequestURL().toString(); String currentURL = hreq.getRequestURI(); // get everything after the context root int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash String targetURL = null; //取得使用者欲前往之 URL,以本例來說,即是 customer.do if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1, currentURL.length()); //判斷使用者從登入畫面(signon.screen)進行驗證工作 if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) { validateSignOn(request, response, chain); // jump out of this method return; } // check if the user is signed on //檢查使用者是否登入過,從 Session 取出登入標記,作為判斷之用 boolean signedOn = false; if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) { signedOn =((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).boolean Value(); } else {
hreq getSession(). setAttribute(SIGNED ON USER, new Boolean(false) /jump to the resource if signed on ∥若已登入過·則結束此 Filter工作進 Filter chain以本例來說 它露 Filter chain中最後一個 Filter,所以就是不做任何事,巖使用者 進入他的目的查面 if(signedOn)( chain. doFilter(request, response) return l find out if the patterns match the target URL /將使用者欲前往之URL與所有保護查面URL做比對,若符合則導入 登入董面( Signon screen) Iterator it= protectedResources key Seto). iterator while(it. hasNexto)i String protectedName=(String)it. nextO Protected Resource resource (ProtectedResource)protectedResources get(protectedName) String urlPattern=resource. getURLPatterno // now check agains the targetURL 若符合則將目的URL存入 Session並轉導至登入查面結束 Filter 工作 if(urlPattern equals( targetURL))( l put the orginal url in the session so others can access hreq. getsession(). setAttribute(ORIGINAL URL, targetURL): config. getServlet Context( getRequestDispatcher("/"+ sign Page). forward(request, response) l Jump out of the filter and go to the next page M/ No matches if we made it to here hain. doFilter(request, response SignOn Filter先取得使用者的目的URL( customer. do),判斷使用者並未登 入,開始比對目的URL是否在保護畫面中’發現 customer.do爲保護畫面’將
hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(false)); } // jump to the resource if signed on //若已登入過,則結束此 Filter 工作,進入 Filter chain,以本例來說, 它為 Filter chain 中最後一個 Filter,所以就是不做任何事,讓使用者 進入他的目的畫面 if (signedOn) { chain.doFilter(request,response); return; } // find out if the patterns match the target URL //將使用者欲前往之 URL 與所有保護畫面 URL 做比對,若符合則導入 登入畫面(signon.screen) Iterator it = protectedResources.keySet().iterator(); while (it.hasNext()) { String protectedName = (String)it.next(); ProtectedResource resource = (ProtectedResource)protectedResources.get(protectedName); String urlPattern = resource.getURLPattern(); // now check agains the targetURL //若符合則將目的 URL 存入 Session,並轉導至登入畫面,結束 Filter 工作 if (urlPattern.equals(targetURL)) { // put the orginal url in the session so others can access hreq.getSession().setAttribute(ORIGINAL_URL, targetURL); config.getServletContext().getRequestDispatcher("/" + signOnPage).forward(request, response); // Jump out of the filter and go to the next page return; } } // No matches if we made it to here chain.doFilter(request,response); } SignOnFilter 先取得使用者的目的 URL(customer.do),判斷使用者並未登 入,開始比對目的 URL 是否在保護畫面中,發現 customer.do 為保護畫面,將