(接上期)作者:欧宣修
图10 编译成功画面重新部署如:build deploy图11 部署成功画面现在我们可开启浏览器,依上述流程重新执行一次,当进入http://localhost:8080/petstore/index.jsp,观察RI Console秀出登入页、登入失败页之URL:图12 登入页、登入失败页之URL从首页点选使用者帐号浏览页,RI Console秀出目的页URL及找出customer.do为保护页:图13 目的页URL及找出customer.do为保护页第二阶段登入画面(signon.screen)可从screendefinitions_en_US.xml找出内容对应档案为signon.jsp,它源码位置在petstore_home/src/apps/petstore/src/docroot,开启它请看约53列:<waf:form name="existingcustomer" action="j_signon_check" method="POST"> <table cellpadding="5" cellspacing="0" border="0"> <tr> <td class="petstore" align="center" colspan="2"> <b>Yes.</b> </td> </tr> <tr> <td class="petstore_form" align="right"> <b>User Name:</b> </td> <td class="petstore_form"> <c:choose> <c:when test="${cookie['bp_signon'] != null && cookie['bp_signon']!=''}"> <waf:input cssClass="petstore_form" type="text" size="15" name="j_username" validation="validation"> <waf:value><c:out value="${cookie['bp_signon'].value}"/></waf:value> </waf:input> </td> </tr> <tr>以下略...这是一个典型的Web-Form输入画面,使用了JSTL及Petstore自已写的自订卷标(Custom Tag),这些卷标的用法不是本文的讨论重点,请读者自行参阅相关文件、书籍,我们将焦点放在流程上,请注意上述的程序片段粗体部份,使用者将帐号(User Name)及密码(Password)输入后按登入(Sign In)钮,服务器(Web Server)会将request传送给” j_signon_check”这个奇怪的URL,我们再回到SignOnFilter,在初始的变量宣告上,可找到这个URL,约70列:public static final String FORM_SIGNON_URL = "j_signon_check";在doFilter()函式可发现下列程序接收Request进行验证,顺便加上侦察程序代码(Debug code),方便待会程序验证://判断使用者从登入画面(signon.screen)进行验证工作if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) { System.out.println("FORM SIGNON CHECK"); validateSignOn(request, response, chain); // jump out of this method return;}接着在validateSignON()函式进行使用者验证工作,从Request取出使用者输入的字段值,若使用者有勾选Remember My UserName(记住我的帐号)功能,则产生Cookie记录使用者帐号,再来透过EJB tier从数据库读取资料进行比对,验证成功则将使用者帐号(USER_NAME)及是否已登入(SIGNED_ON_USER)参数存入Session,从Request取出目的URL(ORIGINAL_URL),将网页转导就会到达我们的目的地-使用者基本资料浏览画面(customer.do);若验证有误则将网页转导到登入失败画面(signon_error.screen),请读者顺便加上侦察程序代码。public void validateSignOn(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { //从Request取出使用者输入的字段值 // convert to a http servlet request for now HttpServletRequest hreq = (HttpServletRequest)request; HttpServletResponse hres = (HttpServletResponse)response; // get the user name String userName = hreq.getParameter(FORM_USER_NAME); // get the password String password = hreq.getParameter(FORM_PASSWORD); // check if the user wants userName set in cookie String rememberUserName = hreq.getParameter(REMEMBER_USERNAME); //若使用者有勾选Remember My User Name(记住我的帐号)功能,则产生Cookie记录使用者帐号 if (rememberUserName != null) { // set a cookie with the username in it Cookie userNameCookie = new Cookie(COOKIE_NAME, userName); // set cookie to last for one month userNameCookie.setMaxAge(2678400); hres.addCookie(userNameCookie); } else { // see if the cookie exists and remove accordingly Cookie[] cookies = hreq.getCookies(); if (cookies != null) { for (int loop=0; loop < cookies.length; loop++) { if (cookies[loop].getName().equals(COOKIE_NAME)) { cookies[loop].setMaxAge(0); hres.addCookie(cookies[loop]); } } } } //透过EJB从数据库读取资料进行比对 //validate against the registered users SignOnLocal signOn = getSignOnEjb(); //请加入侦察程序代码,方便稍候程序验证 System.out.println("进行EJB tier使用者验证"); //帐号及密码验证 boolean authenticated = signOn.authenticate(userName, password); if (authenticated) { //验证成功则将使用者帐号(USER_NAME)及是否已登入(SIGNED_ON_USER)参数存入Session // place a true boolean in the session if (hreq.getSession().getAttribute(USER_NAME) != null) { hreq.getSession().removeAttribute(USER_NAME); } hreq.getSession().setAttribute(USER_NAME, userName); // remove the sign on user key before putting it back in if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) { hreq.getSession().removeAttribute(SIGNED_ON_USER); } hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(true));//将网页转导就会到达我们的目的地-使用者基本资料浏览画面(customer.do) // redirect to the original destination String targetURL =(String)hreq.getSession().getAttribute(ORIGINAL_URL); hres.sendRedirect(targetURL); return; } else { //若验证有误则将网页转导到登入失败画面(signon_error.screen) hres.sendRedirect(signOnErrorPage); return; } } //取得SignOn Local Stateless Session Bean Reference private SignOnLocal getSignOnEjb() throws ServletException { SignOnLocal signOn = null; try { InitialContext ic = new InitialContext(); Object o = ic.lookup("java:comp/env/ejb/local/SignOn"); SignOnLocalHome home =(SignOnLocalHome)o; signOn = home.create(); } catch (javax.ejb.CreateException cx) { throw new ServletException("Failed to Create SignOn EJB: caught "+ cx); } catch (javax.naming.NamingException nx) { throw new ServletException("Failed to Create SignOn EJB: caught "+ nx); } return signOn; }Object o = ic.lookup("java:comp/env/ejb/local/SignOn");透过上述程序代码可追纵SignOnEJB相关信息: (待续)与作者联络: senshaw@ms4.hinet.net---------------------------------------------------------------