优雅而有效 的解决 JSP和Struts 用户退出问题文档格式.docx
《优雅而有效 的解决 JSP和Struts 用户退出问题文档格式.docx》由会员分享,可在线阅读,更多相关《优雅而有效 的解决 JSP和Struts 用户退出问题文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
大部分Web应用不会包含象银行账户或信用卡资料那样机密的信息,但一旦涉及到敏感数据,我们就需要提供一类密码保护机制。
举例来说,一个工厂中工人通过Web访问他们的时间安排、进入他们的训练课程以及查看他们的薪金等等。
此时应用SSL(SecureSocketLayer)有点杀鸡用牛刀的感觉,但不可否认,我们又必须为这些应用提供密码保护,否则,工人(也就是Web应用的使用者)可以窥探到工厂中其他雇员的私人机密信息。
与上述情形相似的还有位处图书馆、医院等公共场所的计算机。
在这些地方,许多用户共同使用几台计算机,此时保护用户的个人数据就显得至关重要。
设计良好编写优秀的应用对用户专业知识的要求少之又少。
我们来看一下现实世界中一个完美的Web应用是如何表现的:
一个用户通过浏览器访问一个页面。
Web应用展现一个登陆页面要求用户输入有效的验证信息。
用户输入了用户名和密码。
此时我们假设用户提供的身份验证信息是正确的,经过了验证过程,Web应用允许用户浏览他有权访问的区域。
用户想退出时,点击退出按钮,Web应用要求用户确认他是否则真的需要退出,如果用户确定退出,Session结束,Web应用重新定位到登陆页面。
用户可以放心的离开而不用担心他的信息会泄露。
另一个用户坐到了同一台电脑前,他点击后退按钮,Web应用不应该出现上一个用户访问过的任何一个页面。
事实上,Web应用在第二个用户提供正确的验证信息之前应当一直停留在登陆页面上。
通过示例程序,文章向您阐述了如何在一个Web应用中实现这一功能。
JSP示例
为了更为有效地阐述实现方案,本文将从展示一个示例应用logoutSampleJSP1中碰到的问题开始。
这个示例代表了许多没有正确解决退出过程的Web应用。
logoutSampleJSP1包含了下述jsp页面:
login.jsp,home.jsp,secure1.jsp,secure2.jsp,logout.jsp,loginAction.jsp,andlogoutAction.jsp。
其中页面home.jsp,secure1.jsp,secure2.jsp,和logout.jsp是不允许未经认证的用户访问的,也就是说,这些页面包含了重要信息,在用户登陆之前或者退出之后都不应该出现在浏览器中。
login.jsp包含了用于用户输入用户名和密码的form。
logout.jsp页包含了要求用户确认是否退出的form。
loginAction.jsp和logoutAction.jsp作为控制器分别包含了登陆和退出代码。
第二个示例应用logoutSampleJSP2展示了如何解决示例logoutSampleJSP1中的问题。
然而,第二个应用自身也是有疑问的。
在特定的情况下,退出问题还是会出现。
第三个示例应用logoutSampleJSP3在第二个示例上进行了改进,比较完善地解决了退出问题。
最后一个示例logoutSampleStruts展示了Struts如何优美地解决登陆问题。
注意:
本文所附示例在最新版本的MicrosoftInternetExplorer(IE),NetscapeNavigator,Mozilla,FireFox和Avant浏览器上测试通过。
Loginaction
BrianPontarelli的经典文章《J2EESecurity:
ContainerVersusCustom》讨论了不同的J2EE认证途径。
文章同时指出,HTTP协议和基于form的认证并未提供处理用户退出的机制。
因此,解决途径便是引入自定义的安全实现机制。
自定义的安全认证机制普遍采用的方法是从form中获得用户输入的认证信息,然后到诸如LDAP(lightweightdirectoryaccessprotocol)或关系数据库的安全域中进行认证。
如果用户提供的认证信息是有效的,登陆动作往HttpSession对象中注入某个对象。
HttpSession存在着注入的对象则表示用户已经登陆。
为了方便读者理解,本文所附的示例只往HttpSession中写入一个用户名以表明用户已经登陆。
清单1是从loginAction.jsp页面中节选的一段代码以此阐述登陆动作:
Listing1
//...
//initializeRequestDispatcherobject;
setforwardtohomepagebydefault
//初始化RequestDispatcher,设置默认转到home.jsp
RequestDispatcherrd=request.getRequestDispatcher("
home.jsp"
);
//Prepareconnectionandstatement预编译连接和SQL表达式,防SQL注入
rs=stmt.executeQuery("
selectpasswordfromUSERwhereuserName='
"
+userName+"
'
//查询此用户名的密码结果集
if(rs.next()){
//Queryonlyreturns1recordintheresultset;
only1只返回密码结果集中的一条数据
passwordperuserNamewhichisalsotheprimarykey
if(rs.getString("
password"
).equals(password)){//Ifvalidpassword密码正确
session.setAttribute("
User"
userName);
//Savesusernamestringinthesessionobject保存用户名到session
}
else{//Passworddoesnotmatch,i.e.,invaliduserpassword密码错误
request.setAttribute("
Error"
"
Invalidpassword."
rd=request.getRequestDispatcher("
login.jsp"
//密码错误转向到登录页面
}//Norecordintheresultset,i.e.,invalidusername
else{
request.setAttribute("
Invalidusername."
//用户名错误
rd=request.getRequestDispatcher("
}
//Asacontroller,loginAction.jspfinallyeitherforwardsto"
or"
rd.forward(request,response);
本文所附示例均以关系型数据库作为安全域,但本文所阐述的观点对任何类型的安全域都是适用的。
Logoutaction
退出动作就包含了简单的删除用户名以及对用户的HttpSession对象调用invalidate()方法。
清单2是从loginoutAction.jsp页面中节选的一段代码以此阐述退出动作:
Listing2
session.removeAttribute("
session.invalidate();
//...
阻止未经认证访问受保护的jsp页面
从form中获取用户提交的认证信息并经过验证后,登陆动作简单地往httpsession对象中写入一个用户名,退出动作则做相反的工作,它从用户的httpsession对象中删除用户名并调用invalidate()方法销毁httpsession。
为了使登陆和退出动作真正发挥作用,所有受保护的jsp页面都应该首先验证httpsession中是否包含了用户名以确认当前用户是否已经登陆。
如果httpsession中包含了用户名,也就是说用户已经登陆,web应用则将剩余的jsp页发送给浏览器,否则,jsp页将跳转到登陆页login.jsp。
页面home.jsp,secure1.jsp,secure2.jsp和logout.jsp均包含清单3中的代码段:
listing3禁止访问只有登录后才能查看的JSP页面
stringusername=(string)session.getattribute("
user"
if(null==username){
request.setattribute("
error"
sessionhasended.pleaselogin."
requestdispatcherrd=request.getrequestdispatcher("
}
//allowtherestofthedynamiccontentinthisjsptobeservedtothebrowser
在这个代码段中,程序从httpsession中减缩username字符串。
如果字符串为空,web应用则自动中止执行当前页面并跳转到登陆页,同时给出sessionhasended.pleaselogin.的提示;
如果不为空,web应用则继续执行,也就是把剩余的页面提供给用户。
运行logoutsample.jsp1
运行logoutsamplejsp1将会出现如下几种情形:
01如果用户没有登陆,web应用将会正确中止受保护页面home.jsp,secure1.jsp,secure2.jsp和logout.jsp的执行,也就是说,假如用户在浏览器地址栏中直接敲入受保护jsp页的地址试图访问,web应用将自动跳转到登陆页并提示sessionhasended.pleaselogin.
02同样的,当一个用户已经退出,web应用也会正确中止受保护页面home.jsp,secure1.jsp,secure2.jsp和logout.jsp的执行
03用户退出后,如果点击浏览器上的后退按钮,web应用将不能正确保护受保护的页面——在sessi