apache wicket_Apache Wicket:记住我的功能

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

apache wicket

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

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

相关文章

linux pap认证,配置PPP PAP 认证

配置PPP PAP 认证&#xff1a;1. 单向认证&#xff1a;R1启动pap R1为主验证方&#xff0c;R2为被验证方。r1(config)#inter s1/0r1(config-if)#ip add 202.146.0.1 255.255.255.0r1(config-if)#no shutdownr1(config-if)#encapsulation pppr1(config-if)#ppp authenticatin pa…

Shell编程关于Sha-Bang(#!)

转载自&#xff1a;http://blog.chinaunix.net/uid-26657936-id-3066136.html Q. #!的名字为什么叫Sha-Bang&#xff1f; A. Sha-Bang是Sharp和Bang的组合词。Sharp for #, Bang for ! 类似的情况是&#xff0c;C#通常被称为C SharpQ. Sha-Bang(#!)是不是注释&#xff1f;A. 不…

您应该保持联系的十大高级Java对话

在线讲座和视频是学习软件开发新事物的主要资源之一。 您可以找到Java专家与您分享他们的经验&#xff0c;而不必坐下来。 在下面的文章中&#xff0c;我们收集了10位我们最喜欢的演讲者和主题&#xff0c;我们相信每个Java开发人员都应该注意。 获取爆米花&#xff0c;坐下来…

c语言定时器作用,Go语言定时器实现原理及作用

对于任何一个正在运行的应用&#xff0c;如何获取准确的绝对时间都非常重要&#xff0c;但是在一个分布式系统中我们很难保证各个节点上绝对时间的一致性&#xff0c;哪怕通过 NTP 这种标准的对时协议也只能把时间的误差控制在毫秒级&#xff0c;所以相对时间在一个分布式系统中…

非常详细的/etc/passwd解释

root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin desktop:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin mengqc:x:500:500:mengqc:/home/mengqc:/bin/bash 在该文件中&#xff0c;每一行用户记录的各个数据段…

QT:基本知识(一);

注&#xff1a; 该博文为扩展型&#xff1b; 1) QString转换为LPCTSTR QString szStr; LPCTSTR str (LPWSTR)(szStr.utf16()); 2) 中文乱码解决&#xff1b; QTextCodec *pCodec QTextCode::codecForName("gb2312"); if(!pCodec) return ""; std…

c语言程序设计实训教材,C语言程序设计实训指导书

摘要&#xff1a;李建中等编著的这本《C语言程序设计实训指导书》为《C语言程序设计》的配套教材.全书共分4部分.第1部分主要介绍Visual C6.0的集成功能界面和操作;第2部分配合主教材的内容,设计了11个实验项目;第3部分对主教材每一章习题给出解答或指导;第4部分为全国计算机等…

SUID SGID

转载自&#xff1a;http://www.cnblogs.com/perseus/articles/2830397.html 如果你对SUID、SGID仍有迷惑可以好好参考一下&#xff01; Copyright by kevintz.由于用户在UNIX下经常会遇到SUID、SGID的概念&#xff0c;而且SUID和SGID涉及到系统安全&#xff0c;所以用户也比较…

动态规划:LIS优化

对于1D/1D动态规划来说&#xff0c;理论时间复杂度都是O&#xff08;n^2&#xff09;的&#xff0c;这种动态规划一般都可以进行优化&#xff0c;贴一篇文章 https://wenku.baidu.com/view/e317b1020740be1e650e9a12.html 这里介绍最简单的一种&#xff0c;LIS的求法 其实就是二…

maven 版本号插件_Maven内部版本号插件–用法示例

maven 版本号插件假设我们需要向一些工件&#xff08;jar&#xff0c;war等&#xff09;添加内部版本号。 在这里&#xff0c;我想演示buildnumber-maven-plugin的用法。 这篇文章基于&#xff1a; http://mojo.codehaus.org/buildnumber-maven-plugin/usage.html http://www…

c语言程序设计课件第二章,c语言程序设计课件张元国 ISBN9787566300386 PPT第二章数据类型 运算符与表达式...

1、第2章 数据类型、运算符与表达式,语言的数据类型 常量与变量 运算符与表达式 不同类型数据间的转换,2.1语言的数据类型,数据是计算机程序处理的所有信息的总称&#xff0c;数值、字符、文本等都是数据&#xff0c;在各种程序设计中几乎都要使用和处理数据&#xff0c;程序设…

nowcoder172C 保护 (倍增lca+dfs序+主席树)

https://www.nowcoder.com/acm/contest/172/C &#xff08;sbw大佬太强啦 orz&#xff09; 先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径&#xff0c;然后就能发现&#xff0c;对于某两个&#xff08;直上直下的&#xff09;路径a,b&#xff0c;b的下端点在a的下端点子树中…

添用户报错:useradd:警告:此主目录已经存在

转载自&#xff1a;http://blog.csdn.net/lele892207980/article/details/17239347 建立mysql用户、组 groupadd mysql useradd -g mysql mysql 然后删除 userdel mysql 再添用户和组加时&#xff0c;提示&#xff1a; useradd&#xff1a;警告&#xff1a;此主目录已经存在。…

专业本的C语言,以解决本专业问题为导向的C语言程序设计课程教学探索

以解决本专业问题为导向的C语言程序设计课程教学探索发布时间:2019-08-07 来源: 摘 要 针对C语言程序设计课程在计算机及其相关专业中存在的“狭义工具论”的教学现状&#xff0c;本着“以应用能力培养为目标、以计算思维为手段”的原则进行知识选取和教学内容、教学案例、教学…

HotSpot增量Java垃圾收集器

在我最近的博客文章“ 确定活动的HotSpot垃圾收集器”中 &#xff0c;我描述了可用于确定HotSpot JVM &#xff08;Java进程&#xff09;正在使用的垃圾收集器&#xff08;当从命令行参数&#xff08;标志&#xff09; 中看不出来&#xff09;时可以使用的不同方法。传递给Java…

修改已存在用户的所属组(usermod用法)

转载自&#xff1a;http://blog.163.com/zhzh_lin/blog/static/40538715200771503221224/ 修改使用者帐号 名称 usermod - 修 改 使 用 者 帐 号 语法 usermod [-c comment] [-d home_dir [ -m]] [-e expire_date] [-f inactive_time] [-g initial_group] [-G group[,.…

c语言如何查找空指针,c语言中的空指针

#include#include#define SAFE_MALLOC(n) safe_malloc(n)#define SAFE_FREE(p)safe_free((int**)(&(p)))//将变量指针赋值为空指针//若变量本身为空&#xff0c;则提示出现野指针void safe_free(int **p){if(*p){free(*p);*p NULL;printf("这不是野指针!!!,好开心. _…

eclipse pmd使用_使用您自己的规则在Eclipse中自定义PMD

eclipse pmd使用PMD是非常好的Java代码扫描程序&#xff0c;可帮助您避免潜在的编程问题。 它可以轻松扩展以满足您的需求&#xff0c;并且本文将为您带来与JPA的Enumerated注释用法相关的自定义PMD规则的简单示例。 在继续阅读之前&#xff0c;您应该检查我以前的文章之一-JPA…

linux bash source 0,linux中BASH_SOURCE[0](转)

在C/C中&#xff0c;__FUNCTION__常量记录当前函数的名称。有时候&#xff0c;在日志输出的时候包含这些信息是非常有用的。而在Bash中&#xff0c;同样有这样一个常量FUNCNAME&#xff0c;但是有一点区别是&#xff0c;它是一个数组而非字符串&#xff0c;其中数组的第一个元素…

如何将自定义数据源集成到Apache Spark中

如今&#xff0c;流数据是一个热门话题&#xff0c;而Apache Spark是出色的流框架。 在此博客文章中&#xff0c;我将向您展示如何将自定义数据源集成到Spark中。 Spark Streaming使我们能够从各种来源进行流传输&#xff0c;同时使用相同的简洁API访问数据流&#xff0c;执行…