大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> JSP专区 -> JSP和Struts解决用户退出问题

JSP和Struts解决用户退出问题

时间: 2021-07-31 作者:daque

  在一个有暗号养护的web运用中,精确处置用户退出进程并不只仅只需挪用httpsession的invalidate()本领。此刻大局部欣赏器上都有畏缩和进步按钮,承诺用户畏缩或进步到一个页面。即使在用户在退出一个web运用后按了畏缩按钮欣赏器把缓存中的页面表露给用户,这会运用户爆发迷惑,她们会发端担忧她们的部分数据能否安定。很多web运用抑制用户退出时封闭所有欣赏器,如许,用户就没辙点击畏缩按钮了。再有少许运用javascript,但在某些存户端欣赏器这却不确定起效率。那些处置计划都很蠢笨且不许保护在任一情景下100%灵验,同声,它也诉求用户有确定的操纵体味。

  这篇作品以示例阐明了精确处置用户退出题目的计划。作家kevin le开始刻画了一个暗号养护web运用,而后以示例步调证明题目怎样爆发并计划处置题目的计划。作品固然是对准jsp页面举行阐明,但作家所阐明的观念很简单领会切不妨为其余web本领所沿用。结果作家展现了怎样用jakarta struts优美地处置这一题目。

  大局部web运用不会包括象钱庄账户或断定卡材料那么神秘的消息,但一旦波及到敏锐数据,咱们就须要供给一类暗号养护体制。举例来说,一个工场台湾中华工程公司人经过web考察她们的功夫安置、加入她们的演练课程以及察看她们的报酬之类。此时运用ssl(secure socket layer)有点杀鸡用牛刀的发觉,但不行含糊,咱们又必需为那些运用供给暗号养护,要不,工人(也即是web运用的运用者)不妨观察到工场中其余雇员的个人神秘消息。

  与上述景象一致的再有位处典籍馆、病院等大众场合的计划机。在那些场合,很多用户共通运用几台计划机,此时养护用户的部分数据就显得至关要害。安排杰出编写特出的运用对用户专科常识的诉求少之又少。

  咱们来看一下实际寰球中一个完备的web运用是怎样展现的:一个用户经过欣赏器考察一个页面。web运用展示一个登岸页面诉求用户输出灵验的考证消息。用户输出了用户名和暗号。此时咱们假如用户供给的身份考证消息是精确的,过程了考证进程,web运用承诺用户欣赏他有权考察的地区。用户想退出时,点击退出按钮,web运用诉求用户确认他能否则真的须要退出,即使用户决定退出,session中断,web运用从新定位到登岸页面。用户不妨释怀的摆脱而不必担忧他的消息会揭发。另一个用户坐到了同一台电脑前,他点击畏缩按钮,web运用不该当展示上一个用户考察过的任何一个页面。究竟上,web运用在第二个用户供给精确的考证消息之前该当从来中断在登岸页面上。经过示例步调,作品向您阐明了怎样在一个web运用中实行这一功效。

  jsp示例

  为了更为灵验地阐明实行计划,正文将从展现一个示例运用logoutsamplejsp第11中学碰到的题目发端。这个示例代办了很多没有精确处置退出进程的web运用。logoutsamplejsp1包括了下述jsp页面:login.jsp, home.jsp, secure1.jsp, secure2.jsp, logout.jsp, loginaction.jsp, and logoutaction.jsp。个中页面home.jsp, secure1.jsp, secure2.jsp, 和logout.jsp是不承诺一经认证的用户考察的,也即是说,那些页面包括了要害消息,在用户登岸之前大概退出之后都不该当出此刻欣赏器中。login.jsp包括了用来用户输出用户名和暗号的form。logout.jsp页包括了诉求用户确认能否退出的form。loginaction.jsp和logoutaction.jsp动作遏制器辨别包括了登岸和退出代码。

  第二个示例运用logoutsamplejsp2展现了怎样处置示例logoutsamplejsp第11中学的题目。但是,第二个运用自己也是有疑义的。在一定的情景下,退出题目仍旧会展示。

  第三个示例运用logoutsamplejsp3在第二个示例长进行了矫正,比拟完备地处置了退出题目。

  结果一个示例logoutsamplestruts展现了struts怎样幽美地处置登岸题目。

  提防:正文所附示例在最新本子的microsoft internet explorer (ie), netscape navigator, mozilla, firefox和avant欣赏器上尝试经过。

  login action

  brian pontarelli的典范作品《j2ee security: container versus custom》计划了各别的j2ee认证道路。作品同声指出,http和议和鉴于form的认证并未供给处置用户退出的体制。所以,处置道路便是引入自设置的安定实行体制。

  自设置的安定认证体制一致沿用的本领是从form中赢得用户输出的认证消息,而后到诸如ldap (lightweight directory access protocol)或联系数据库的安定域中举行认证。即使用户供给的认证消息是灵验的,登岸举措往httpsession东西中注入某个东西。httpsession生存着注入的东西则表白用户仍旧登岸。为了简单读者群领会,正文所附的示例只往httpsession中写入一个用户名以表白用户仍旧登岸。清单1是从loginaction.jsp页面中节选的一段代码以此阐明登岸举措:

listing 1 //...//initialize requestdispatcher object; set forward to home page by defaultrequestdispatcher rd = request.getrequestdispatcher("home.jsp");

//prepare connection and statementrs = stmt.executequery("select password from user where username = '" + username + "'");if (rs.next()) {  //query only returns 1 record in the result set; only 1  password per username which is also the primary key if (rs.getstring("password").equals(password)) { //if valid password  session.setattribute("user", username); //saves username string in the session object } else { //password does not match, i.e., invalid user password  request.setattribute("error", "invalid password.");

  rd = request.getrequestdispatcher("login.jsp"); }} //no record in the result set, i.e., invalid usernameelse {

 request.setattribute("error", "invalid user name."); rd = request.getrequestdispatcher("login.jsp");}}

//as a controller, loginaction.jsp finally either forwards to "login.jsp" or "home.jsp"rd.forward(request, response);//...

  正文所附示例均以联系型数据库动作安定域,但正文所阐明的看法对任何典型的安定域都是实用的。

  logout action

  退出举措就包括了大略的简略用户名以及对用户的httpsession东西挪用invalidate()本领。清单2是从loginoutaction.jsp页面中节选的一段代码以此阐明退出举措:

listing 2 //...session.removeattribute("user");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中的代码段:

listing 3 //...string username = (string) session.getattribute("user");if (null == username) { request.setattribute("error", "session has ended. please login."); requestdispatcher rd = request.getrequestdispatcher("login.jsp"); rd.forward(request, response);}//...//allow the rest of the dynamic content in this jsp to be served to the browser//...

  在这个代码段中,步调从httpsession中减缩username字符串。即使字符串为空,web运用则机动遏止实行暂时页面并跳转到登岸页,同声给出session has ended. please log in.的提醒;即使不为空,web运用则连接实行,也即是把结余的页面供给给用户。

  运转logoutsamplejsp1

  运转logoutsamplejsp1将会展示如次几种景象:

  1) 即使用户没有登岸,web运用将会精确遏止受养护页面home.jsp, secure1.jsp, secure2.jsp和logout.jsp的实行,也即是说,假设用户在欣赏器地方栏市直接敲入受养护jsp页的地方试图考察,web运用将机动跳转到登岸页并提醒session has ended.please log in.

  2) 同样的,当一个用户仍旧退出,web运用也会精确遏止受养护页面home.jsp, secure1.jsp, secure2.jsp和logout.jsp的实行

  3) 用户退出后,即使点击欣赏器上的畏缩按钮,web运用将不许正保证护受养护的页面——在session废弃后(用户退出)受养护的jsp页从新在欣赏器中表露出来。但是,即使用户点击归来页面上的任何链接,web运用将会跳转到登岸页面并提醒session has ended.please log in.

  遏止欣赏器缓存

  上述题目的基础在乎大局部欣赏器都有一个畏缩按钮。当点击畏缩按钮时,默许情景下欣赏器不是从web效劳器上从新获得页面,而是从欣赏器缓存中载入页面。鉴于java的web运用并未控制这一功效,在鉴于php、asp和.net的web运用中也同样生存这一题目。

  在用户点击畏缩按钮后,欣赏器到效劳器再从效劳器到欣赏器如许常常道理上的http回路并没有创造,只是不过用户,欣赏器平静存举行了交互。以是,纵然包括了清单3上的代码来养护jsp页面,当点击畏缩按钮时,那些代码是不会实行的。

  缓存的是非,真是仁者见仁智者见智。缓存简直供给了少许便当,但常常只在运用静态的html页面或鉴于图形或感化的页面你本领感遭到。而另一上面,web运用常常是鉴于数据的,数据常常是一再变动的。与从缓存中读取并表露过时的数据比拟,供给最新的数据才是更要害的!

  倒霉的是,http头消息“expires”和“cache-control”为运用步调效劳器供给了一个遏制欣赏器和代劳效劳器上缓存的体制。http头消息expires报告代劳效劳器它的缓存页面何时将过时。http1.1典型中新设置的头消息cache-control不妨报告欣赏器不缓存任何页面。当点击畏缩按钮时,欣赏珍视新考察效劳器已获得页面。如次是运用cache-control的基础本领:

  1) no-cache:强迫缓存从效劳器上获得新的页面

  2) no-store: 在任何情况下缓存不生存任何页面

  http1.0典型中的pragma:no-cache同等于http1.1典型中的cache-control:no-cache,同样不妨包括在头消息中。

  经过运用http头消息的cache遏制,第二个示例运用logoutsamplejsp2处置了logoutsamplejsp1的题目。logoutsamplejsp2与logoutsamplejsp1各别表此刻如次代码段中,这一代码段介入进一切受养护的页面中:

//...response.setheader("cache-control","no-cache"); //forces caches to obtain a new copy of the page from the origin serverresponse.setheader("cache-control","no-store"); //directs caches not to store the page under any circumstanceresponse.setdateheader("expires", 0); //causes the proxy cache to see the page as "stale"response.setheader("pragma","no-cache"); //http 1.0 backward compatibilitystring username = (string) session.getattribute("user");if (null == username) { request.setattribute("error", "session has ended. please login."); requestdispatcher rd = request.getrequestdispatcher("login.jsp"); rd.forward(request, response);}//...

  经过树立头消息和查看httpsession中的用户名保证了欣赏器不缓存页面,同声,即使用户未登岸,受养护的jsp页面将不会发送给欣赏器,取而代之的将是登岸页面login.jsp。

  运转logoutsamplejsp2

  运转logoutsamplejsp2后将回看到如次截止:

  1) 当用户退出后试图点击畏缩按钮,欣赏器并不会表露受养护的页面,它只会实际登岸页login.jsp同声给出提醒消息session has ended. please log in.

  2) 但是,当按了畏缩按钮归来的页是处置用户提交数据的页面时,ie和avant欣赏器将弹出如次消息提醒:

  劝告:页面已过时……(你确定见过)

  采用革新后前一个jsp页面将从新表露在欣赏器中。很明显,这不是咱们所想看到的由于它违反了logout举措的手段。爆发这一局面时,很大概是一个歹意用户在试验获得其余用户的数据。但是,这个题目只是出此刻畏缩按钮对应的是一个处置post乞求的页面。

  记载结果登岸功夫

  上述题目之以是展示是由于欣赏器将其缓存中的数据从新提交了。这正文的例子中,数据包括了用户名和暗号。不管能否给出安定劝告消息,欣赏器此时起到了反面效率。

  为领会决logoutsamplejsp第22中学展示的题目,logoutsamplejsp3的login.jsp在包括username和password的普通上还包括了一个称作lastlogon的湮没表单域,此表单域动静的用一个long型值初始化。这个long型值是挪用system.currenttimemillis()获得到的自1970年1月1日此后的毫秒数。当login.jsp中的form提交时,loginaction.jsp开始将湮没域中的值与用户数据库中的值举行比拟。惟有当lastlogon表单域中的值大于数据库中的值时web运用才觉得这是个灵验的登岸。

  为了考证登岸,数据库中lastlogon字段必需以表单中的lastlogon值举行革新。上例中,当欣赏珍视复提交数据时,表单中的lastlogon值不比数据库中的lastlogon值大,所以,loginaction转到login.jsp页面,并提醒session has ended.please log in.清单5是loginaction中节选的代码段:

  清单5

//...requestdispatcher rd = request.getrequestdispatcher("home.jsp"); //forward to homepage by default//...if (rs.getstring("password").equals(password)) {  //if valid password long lastlogondb = rs.getlong("lastlogon"); if (lastlogonform > lastlogondb) {  session.setattribute("user", username); //saves username string in the session object  stmt.executeupdate("update user set lastlogon= " + lastlogonform + " where username = '" + username + "'"); } else {  request.setattribute("error", "session has ended. please login.");  rd = request.getrequestdispatcher("login.jsp"); } } else { //password does not match, i.e., invalid user password  request.setattribute("error", "invalid password.");  rd = request.getrequestdispatcher("login.jsp");  } //... rd.forward(request, response);//...

  为了实行上述本领,你必需记载每个用户的结果登岸功夫。对于沿用联系型数据库安定域来说,这点不妨不妨经过在某个表中加上lastlogin字段轻快实行。ldap以及其余的安定域须要略微动下思想,但很明显是不妨实行的。

  表白结果登岸功夫的本领有很多。示例logoutsamplejsp3运用了自1970年1月1日此后的毫秒数。这个本领在很多人在各别欣赏器顶用一个用户账号登岸时也是可行的。

  运转logoutsamplejsp3

  运转示例logoutsamplejsp3将展现怎样精确处置退出题目。一旦用户退出,点击欣赏器上的畏缩按钮在任何情景下都不会是受养护的页面在欣赏器上表露出来。这个示例展现了怎样精确处置退出题目而不须要特殊的培养和训练。

  为了使代码更简单灵验,少许冗余的代码不妨剔除掉。一种道路即是把清单4中的代码写到一个独立的jsp页中,经过标签<jsp:include>其余页面也不妨援用。

  struts框架下的退出实行

  与径直运用jsp或jsp/servlets比拟,另一个可选的计划是运用struts。为一个鉴于struts的web运用增添一个处置退出题目的框架不妨优美地不费实力的实行。这局部归功于struts是沿用mvc安排形式的所以将模子和视图明显的划分。其余,java是一个面向东西的谈话,其扶助接受,不妨比jsp中的剧本更为简单地实行代码重用。在struts中,清单4中的代码不妨从jsp页面中移植到action类的execute()本领中。其余,咱们还不妨设置一个接受struts action类的基础类,其execute()本领中包括了清单4中的代码。经过运用类接受体制,其余类不妨接受基础类中的通用论理来树立http头消息以及检索httpsession东西中的username字符串。这个基础类是一个笼统类并设置了一个笼统本领executeaction()。一切接受自基类的子类都应实行exectuteaction()本领而不是掩盖它。清单6是基类的局部代码:

  清单6

public abstract class baseaction extends action { public actionforward execute(actionmapping mapping, actionform form,httpservletrequest request, httpservletresponse response)  throws ioexception, servletexception {  response.setheader("cache-control","no-cache");   //forces caches to obtain a new copy of the page from the origin server  response.setheader("cache-control","no-store");  //directs caches not to store the page under any circumstance  response.setdateheader("expires", 0); //causes the proxy cache to see the page as "stale"  response.setheader("pragma","no-cache"); //http 1.0 backward compatibility

  if (!this.userisloggedin(request)) {   actionerrors errors = new actionerrors();   errors.add("error", new actionerror("logon.sessionended"));   this.saveerrors(request, errors);   return mapping.findforward("sessionended");  }  return executeaction(mapping, form, request, response); }

 protected abstract actionforward executeaction(actionmapping mapping, actionform form, httpservletrequest request, httpservletresponse response)  throws ioexception, servletexception;

 private boolean userisloggedin(httpservletrequest request) {  if (request.getsession().getattribute("user") == null) {   return false;  }

  return true; }}

  清单6中的代码与清单4中的很好像,只是不过用actionmapping findforward代替了requestdispatcher forward。清单6中,即使在httpsession中未找到username字符串,actionmapping东西将找到名为sessionended的forward元素并跳转到对应的path。即使找到了,子类将实行本来现了executeaction()本领的交易论理。所以,在摆设文献struts-web.xml中为一切子类证明个一名为sessionended的forward元素是必需的。清单7以secure1 action阐领会如许一个证明:

  清单7

<action path="/secure1" type="com.kevinhle.logoutsamplestruts.secure1action" scope="request"><forward name="success" path="/web-inf/jsps/secure1.jsp"/><forward name="sessionended" path="/login.jsp"/></action>

  接受自baseaction类的子类secure1action实行了executeaction()本领而不是掩盖它。secure1action类不实行任何退出代码,如清单8:

public class secure1action extends baseaction { public actionforward executeaction(actionmapping mapping, actionform form,httpservletrequest request, httpservletresponse response) throws ioexception, servletexception {

  httpsession session = request.getsession();   return (mapping.findforward("success")); }}

  只须要设置一个基类而不须要特殊的代码处事,上述处置计划是优美而灵验的。尽管还好吗,将通用的动作本领写成一个接受strutsaction的基类是很多struts项手段共通体味,犯得着引荐。

  论断

  正文阐明领会决退出题目的计划,纵然计划大略的令人诧异,但却在一切情景下都能灵验地处事。不管是对jsp仍旧struts,所要做的然而是写一段不胜过50行的代码以及一个记委派户结果登岸功夫的本领。在web运用中搀和运用那些计划不妨使称赞的个人数据不致揭发,同声,也能减少用户的体味。

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.