Apache Wicket:记住我的功能

在Web应用程序中,具有“记住我”功能非常普遍,该功能使用户每次访问我们的网站时都能自动登录。

可以使用Spring Security来实现这种功能,但我认为将基于请求的身份验证框架与基于组件的Web框架结合使用并不是最好的主意。 这两个世界不能很好地融合在一起,所以我更喜欢使用我自己的烘焙解决方案,我将在下面介绍。

基础项目

我们从一个简单的Web应用程序开始,该应用程序使用最新的仍很热门的Apache Wicket 6编写。 您可以从GitHub下载完整的源代码,并使用mvn clean compile jetty:run启动应用程序。

基本应用程序包含两个页面:

  • 主页:显示已登录和未登录用户的欢迎消息,或者注销或登录链接。
  • 登录页面:允许用户基于简单的用户内存集合进行登录。 一些有效的登录名/密码对:John / john,Lisa / lisa,Tom / tom。

记住我的功能

实现“记住我”功能的标准方法如下:

  1. 询问用户是否希望他将来被记住并自动登录。
  2. 如果是这样,请在他的计算机上使用登录名和密码保存cookie。
  3. 对于每个访问我们网站的新用户,请检查是否存在步骤2中的cookie,如果存在,则为自动登录用户。
  4. 当他手动注销时,请删除cookie,以便可以清除用于自动登录的数据。

第二点需要一些解释。 在此示例应用程序中,我们将保存登录信息,而不是哈希值,即 cookie中未加密的密码。 在实际情况下,这是不可接受的。 取而代之的是,您应该考虑存储散列和加盐的密码,这样,即使有人拦截了用户Cookie,密码仍然是秘密的,需要更多的工作来对其进行解码。
更新: Micha? Mat?oka发布了两个非常有趣的链接,这些链接如何在实际系​​统中完成。 这些方法甚至不使用密码或密码哈希。 有关更多详细信息,请查看此帖子下方的他的评论。

第1步:作为用户,我想决定是否要使用“记住我”功能

链接以提交此步骤

为了允许用户通知应用程序他想使用“记住我”功能,我们只需在登录页面添加一个复选框即可。 因此,我们需要稍微修改LoginPage Java和html文件(突出显示新内容):

<form wicket:id='form' class='form-horizontal'><fieldset><legend>Please login</legend></fieldset><div class='control-group'><div wicket:id='feedback'></div></div><div class='control-group'><label class='control-label' for='login'>Login</label><div class='controls'><input type='text' id='login' wicket:id='login' /></div></div><div class='control-group'><label class='control-label' for='password'>Password</label><div class='controls'><input type='password' id='password' wicket:id='password' /></div></div><div class='control-group'><div class='controls'><label class='checkbox'><input type='checkbox' wicket:id='rememberMe'> Remember me on this computer</label></div></div><div class='form-actions'><input type='submit' wicket:id='submit' value='Login' title='Login' class='btn btn-primary'/></div></form>
private String login;private String password;private boolean rememberMe;public LoginPage() {Form<Void> loginForm = new Form<Void>('form');add(loginForm);loginForm.add(new FeedbackPanel('feedback'));loginForm.add(new RequiredTextField<String>('login', new PropertyModel<String>(this, 'login')));loginForm.add(new PasswordTextField('password', new PropertyModel<String>(this, 'password')));loginForm.add(new CheckBox('rememberMe', new PropertyModel<Boolean>(this, 'rememberMe')));Button submit = new Button('submit') {// (...)};loginForm.add(submit);}

现在我们准备好下一步。

步骤2:作为系统,我想将登录名和密码保存在Cookie中

链接以提交此步骤

首先,我们需要一个CookieService,它将封装负责处理cookie的所有逻辑:在需要时保存,列出和清除cookie。 代码非常简单,我们使用WebResponse和WebRequest类来修改用户浏览器中的cookie。

public class CookieService {public Cookie loadCookie(Request request, String cookieName) {List<Cookie> cookies = ((WebRequest) request).getCookies();if (cookies == null) {return null;}for (Cookie cookie : cookies) {if(cookie.getName().equals(cookieName)) {return cookie;}}return null;}public void saveCookie(Response response, String cookieName, String cookieValue, int expiryTimeInDays) {Cookie cookie = new Cookie(cookieName, cookieValue);cookie.setMaxAge((int) TimeUnit.DAYS.toSeconds(expiryTimeInDays));((WebResponse)response).addCookie(cookie);}public void removeCookieIfPresent(Request request, Response response, String cookieName) {Cookie cookie = loadCookie(request, cookieName);if(cookie != null) {((WebResponse)response).clearCookie(cookie);}}
}

然后,当用户在LoginPage上选中“记住我”时,我们必须在其浏览器中保存cookie:

Button submit = new Button('submit') {@Overridepublic void onSubmit() {UserService userService = WicketApplication.get().getUserService();User user = userService.findByLoginAndPassword(login, password);if(user == null) {error('Invalid login and/or password. Please try again.');}else {UserSession.get().setUser(user);if(rememberMe) {CookieService cookieService = WicketApplication.get().getCookieService();cookieService.saveCookie(getResponse(), REMEMBER_ME_LOGIN_COOKIE, user.getLogin(), REMEMBER_ME_DURATION_IN_DAYS);cookieService.saveCookie(getResponse(), REMEMBER_ME_PASSWORD_COOKIE, user.getPassword(), REMEMBER_ME_DURATION_IN_DAYS);}setResponsePage(HomePage.class);}}};

第3步:作为用户,我想在返回Web应用程序时自动登录

链接以提交此步骤

为了检查用户进入我们的应用程序是否是“使用户自动登录”,我们必须丰富负责创建新用户会话的逻辑。 当前,它是在WicketApplication类中完成的,该类在被请求时创建新的WebSession实例。 因此,每次创建新会话时,我们都必须检查cookie是否存在,以及它们是否为有效的用户名/密码对,请自动登录该用户。

因此,让我们开始将与会话相关的逻辑提取到名为SessionProvider的单独的类中。 它将需要UserService和CookieService来检查现有用户和cookie,因此我们将它们作为构造函数中的引用传递。

public class WicketApplication extends WebApplication {private UserService userService = new UserService();private CookieService cookieService = new CookieService();private SessionProvider sessionProvider = new SessionProvider(userService, cookieService);@Overridepublic Session newSession(Request request, Response response) {return sessionProvider.createNewSession(request);}
}

SessionProvider的作用是创建新的UserSession,检查是否存在正确的cookie,如果存在,则设置登录用户。 此外,我们添加了反馈消息,以通知用户他已被自动记录。 因此,让我们看一下代码:

public class SessionProvider {public SessionProvider(UserService userService, CookieService cookieService) {this.userService = userService;this.cookieService = cookieService;}public WebSession createNewSession(Request request) {UserSession session = new UserSession(request);Cookie loginCookie = cookieService.loadCookie(request, REMEMBER_ME_LOGIN_COOKIE);Cookie passwordCookie = cookieService.loadCookie(request, REMEMBER_ME_PASSWORD_COOKIE);if(loginCookie != null && passwordCookie != null) {User user = userService.findByLoginAndPassword(loginCookie.getValue(), passwordCookie.getValue());if(user != null) {session.setUser(user);session.info('You were automatically logged in.');}}return session;}
}

为了在HomePage.java上显示反馈消息,我们必须在该处添加FeedbackPanel,但是为了简洁起见,我将在本文中省略它。 您可以阅读commit来检查如何做。

因此,经过三步,我们应该使“记住我”成为可能。 要快速检查它,请通过添加以下内容来修改web.xml文件中的会话超时:

<session-config><session-timeout>1</session-timeout></session-config>

然后启动应用程序mvn clean compile jetty:run ,进入登录页面,登录,关闭浏览器,并在1分钟后(会话终止时)在http:// localhost:8080上再次打开它。 您应该会看到以下内容:

这样就可以了。 但是我们还需要做一件事:允许用户删除Cookie并关闭自动登录。

第4步:作为用户,我希望能够注销并清除我的Cookie

链接以提交此步骤 在最后一步,我们必须允许用户清除其数据并禁用其帐户的“记住我”。 这将通过在用户明确单击“注销”链接时清除两个cookie来实现。

Link<Void> logoutLink = new Link<Void>('logout') {@Overridepublic void onClick() {CookieService cookieService = WicketApplication.get().getCookieService();cookieService.removeCookieIfPresent(getRequest(), getResponse(), SessionProvider.REMEMBER_ME_LOGIN_COOKIE);cookieService.removeCookieIfPresent(getRequest(), getResponse(), SessionProvider.REMEMBER_ME_PASSWORD_COOKIE);UserSession.get().setUser(null);UserSession.get().invalidate();}};logoutLink.setVisible(UserSession.get().userLoggedIn());add(logoutLink);


摘要

就是这样。 在此端口中,我们已经在使用Apache Wicket编写的Web应用程序中实现了简单的“记住我”功能,而无需使用任何外部身份验证库。

祝您编程愉快,别忘了分享!

参考:来自Code Hard Go Pro博客的JCG合作伙伴 Tomasz Dziurko的Apache Wicket中的“记住我”功能 。


翻译自: https://www.javacodegeeks.com/2012/09/apache-wicket-remember-me-functionality.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu 安装中文

系统环境&#xff1a; 1. 官网 http://pinyin.sogou.com/linux/ 下载安装包。 2. 先运行 apt-get update 。 3. 再运行 apt-get -f install 。 4. 再运行 可能有的UBuntu系统自带了。 5. 如果下载的搜狐输入法安装包的格式为 .deb 的&#xff0c; 运行 &#xff1a; dpk…

Eigen教程(10)

整理下Eigen库的教程&#xff0c;参考&#xff1a;http://eigen.tuxfamily.org/dox/index.html 混淆 在Eigen中&#xff0c;当变量同时出现在左值和右值&#xff0c;赋值操作可能会带来混淆问题。这一篇将解释什么是混淆&#xff0c;什么时候是有害的&#xff0c;怎么使用做。 …

matlab把符号数,Matlab 符号与数值之间的转换

符号运算得到的是精确的解析解&#xff0c;但是有时需要进行数值转换&#xff0c;主要通过以下几个函数实现。1.digits 函数调用方法&#xff1a;digits(D)函数设置有效数字个数为D的近似解精度。2.vpa 函数vpaVariable-precision arithmeticSyntaxR vpa(A)R vpa(A,d)Descrip…

JSF组件库–质量不只是零缺陷

自从我上次研究三个主要JSF组件库的质量以来&#xff0c;已经有一段时间了。 2009年12月&#xff0c;我开始比较RichFaces&#xff0c;Primefaces和ICEfaces的整体软件质量 。 从那时起&#xff0c;事情发生了变化&#xff0c;从现在开始&#xff0c;我想重新评估和更新它。 我…

[API档案]GetDlgItem

函数功能 用于获取指定对话框函数控件的句柄。 API函数原型 1 HWND WINAPI GetDlgItem( 2 _In_opt_ HWND hDlg, //指向包含该对话框的句柄 3 _In_ int nIDDlgItem //第二个参数是控件的名称 4 ); 范例 可参见ComboBox_AddString宏的范例【点击这里】转载于:ht…

嵌入式实时系统的任务设计

嵌入式实时系统的任务设计主要为任务函数的设计、任务优先级的安排、任务的数据结构设计&#xff0c;任务之间的同步与通信设计。 一&#xff0e;任务函数的设计 任务函数按任务结构可分为单次执行任务、周期执行任务和事件触发任务&#xff0c;各任务的主要差异点如下&#xf…

mssql php 5.4,PHP5.4如何连接MSSql Server2005

windows系统下&#xff0c;PHP5.3以上的版本已经不支持mssql扩展&#xff0c;所以如果你需要和sql server通信需要到http://msdn.microsoft.com/en-us/sqlserver/ff657782.aspx自行下载微软提供的The SQL Server Driver for PHP。下载后解压缩&#xff0c;将所有的.dll文件拷贝…

将原生SQL功能休眠到您的Spring Data Repository中

JPA为您提供NamedNativeQuery以便使用本机SQL。 但是&#xff0c;用法不是很方便&#xff0c;尤其是当您需要在本机SQL中映射多个实体时。 您必须定义一组容易出错的SqlResultSetMapping映射。 对于以前使用过Hibernate本机SQL功能的用户&#xff0c;您会发现它比JPA的NamedNat…

创建yii的第一个应用

原文链接转载于:https://www.cnblogs.com/Baronboy/p/6354522.html

字符串匹配(KMP 算法 含代码)

主要是针对字符串的匹配算法进行解说 有关字符串的基本知识传统的串匹配法模式匹配的一种改进算法KMP算法网上一比較易懂的解说小样例1计算next 2计算nextval代码有关字符串的基本知识 串&#xff08;string或字符串&#xff09;是由零个或多个字符组成的有限序列&#xff0c;一…

php数组转为js json,javascript-将数组php转换为JSON时出错

我在将多维PHP数组转换为JSON时遇到了一些麻烦.我使用json_encode进行了转换,但它为null.我正在尝试开发orgChart,数据是从CSV文件中读取的,并保存在数组中.布局和JS代码用于接收JSON文件,因此我需要使用这种格式.这是数组的一部分,其中包含175个数组Array([2] > Array([id]…

UVa 10954 全部相加(Huffman编码)

https://vjudge.net/problem/UVA-10954 题意&#xff1a;有n个数的集合S&#xff0c;每次可以从S中删除两个数&#xff0c;然后把它们的和放回集合&#xff0c;直到剩下一个数。每次操作的开销等于删除的两个数之和&#xff0c;求最小开销。 思路&#xff1a;Huffman编码。 1 #…

serialVersionUID的作用以及如何用idea自动生成实体类的serialVersionUID

转载&#xff1a;http://blog.csdn.net/liuzongl2012/article/details/45168585 serialVersionUID的作用&#xff1a; 通过判断实体类的serialVersionUID来验证版本一致性的。在进行反序列化时&#xff0c;JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVer…

js post方式请求另外一个php,利用JS使用POST方式提交请求的方法(结合代码详细解答)...

下面是我给大家整理的利用JS使用POST方式提交请求的方法&#xff0c;有兴趣的同学可以去看看。一般都是写上隐藏的form标签&#xff0c;用来调用js函数然后submit全部用js来写也行&#xff0c;以下是我在一个问答频道看见别人写的例子&#xff0c;放在这里function post(URL, P…

JBoss BRMS最佳实践– BPM流程初始化层的提示

我过去发布过一些有关迁移策略的文章&#xff0c;仔细研究了流程层&#xff0c;并提供了一些有关jBPM的最佳实践 &#xff0c;它们都涉及到BPM策略的非常具体的部分。 我想重新讨论最佳实践的主题&#xff0c;然后在智能集成企业级别上&#xff0c;我们讨论使用JBoss BRMS对您的…

寒假作业二:汇总随笔

随笔一&#xff1a;解题思路随笔二&#xff1a;自学计划 转载于:https://www.cnblogs.com/mercuialC/p/6359997.html

跨站点脚本(XSS)和预防

如OWASP网站&#xff08;https://www.owasp.org/index.php/Cross-site_Scripting_(XSS&#xff09;&#xff09;所述&#xff0c;跨站点脚本&#xff08;XSS&#xff09;攻击的变种几乎是无限的。 在这里&#xff0c;我建议使用基于Servlet筛选器的解决方案来清理HTTP请求。 攻…

NoSQL入门第一天——NoSQL入门与基本概述

一、课程大纲 二、入门概述 1.为什么用NoSQL 单机MySQL的年代&#xff1a; 一个网站的访问量一般都不大&#xff0c;用单个数据库完全可以轻松应付。      我们来看看数据存储的瓶颈是什么&#xff1f;        1.数据量的总大小 一个机器放不下时。&#xff08;现…

随机森林特征个数mtry matlab,基于随机森林的特征选择算法

2.1 算法描述本文提出了一种基于随机森林的Wrapper特征选择方法RFFS,利用随机森林算法的变量重要性度量对特征进行排序,然后采用序列后向搜索方法,每次从特征集合中去掉一个最不重要(重要性得分最小)的特征,逐次进行迭代,并计算分类正确率,最终得到变量个数最少、分类正确率最高…

matlab循环读取变量,Matlab for 多个变量循环能不能这样啊 ,求教高手!!!!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼for a0.003:0.0005:1; b0.002:0.0005:0.9; c0.001:0.0005:0.8;d0.0005:0.0005:0.7;E1a* E_Bone;E2b* E_Bone;E3c* E_Bone;E4d* E_Bone;G1a* G_Bone;G2b* G_Bone;G3c* G_Bone;G4d* G_Bone;%% Integration for cortical bone partsIn…