使用者基本数据浏览流程
=======================
现在让我们进入主题-
Petstore
商业逻辑,笔者以使用者基本资料浏览流程为例,请激活
cloudscape
数据库:
cloudscape –start
图
1
激活数据库
接着激活
RI Application Server(
应用服务器
)
:
j2ee –verbose
图
2
激活
RIPetstore
系统激活无误后,请开启浏览器,输入
http://localhost:8080/petstore/index.jsp
图
3
进入
Petstore
系统
进入系统看到那大大的鹦鹉头,请点选右上角的
”Account”
连结,
进入使用者登入流程:
图
4 Petstore
首页
我们会看到登入画面,直接使用预设的使用者
(j2ee)
及密码
(j2ee)
,
点选
”Sign In”
钮:
图
5
登入画面
看到以下显示个人信息画面就表示我们已登入成功啦!
图
6
个人信息画面
若此时我们按浏览器之
”
上一页
”
钮返回首页:
图
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.
重复第一阶段动作,
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/SignOnFilter.java
。
先看
SignOnFilter
初始动作,约在
87
列:
public void init(FilterConfig config) throws ServletException { this.config = config; URL protectedResourcesURL = null; try { //
謮取
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> <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)).booleanValue(); } 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; } // 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
为保护画面,将
customer.do
此目的
URL
存入
Session
,将
request
转导至登入画面
(signon.screen)
,要求使用者进行登入动作。
第一阶段验证口说无凭,我们可加入侦察程序代码来验证程序是否如笔者所述般运行,请在SignOnFilter.init()加入两行程序:public void init(FilterConfig config) throws ServletException { this.config = config; URL protectedResourcesURL = null; try { //謮取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(); //请加入侦察程序代码 System.out.println("signOnPage="+signOnPage); System.out.println("signErrorPage="+signOnErrorPage); //读取所有欲保护画面,组成HashMap protectedResources = dao.getProtectedResources(); } catch (java.net.MalformedURLException ex) { System.err.println("SignonFilter: malformed URL exception: " + ex); }}doFilter()亦加入侦察程序代码: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()); //请加入侦察程序代码 System.out.println("targetURL="+targetURL); //判断使用者从登入画面(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)).booleanValue(); } 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; } // 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)) { //请加入侦察程序代码 System.out.println("URL Matched! urlPattern="+urlPattern); // 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);}接着请重新编译及部署新的程序代码,在命令模式下:切换至Petstore_home/ src/webservices/apps/petstore/src目录如:cd D:/petstore1.3.1/src/webservices/apps/petstore/src重新编译程序如:build all
转载请注明原文地址: https://ibbs.8miu.com/read-838.html