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

apache wicket_Apache Wicket:记住我的功能相关推荐

  1. Apache Wicket:记住我的功能

    在Web应用程序中,具有"记住我"功能非常普遍,该功能使用户每次访问我们的网站时都能自动登录. 可以使用Spring Security来实现这种功能,但我认为将基于请求的身份验证框 ...

  2. 如何安全实现“记住我”的功能

    一."记住我"的功能不安全的地方 登录之后,让我们来看看cookies 如果你没勾选"记住我"的话,这些要命的信息是不会被cookie记录的,所以那个功能原本也 ...

  3. 安卓实现记住密码登陆功能

    在安卓程序中,我们经常会使用到很多登陆的功能,会看到很多记住密码的地方.这里,我给大家写一个简单的记住密码的功能.注意,这里是简单的记住密码功能,仅用于练习学习用哦.这个程序主要是给学习安卓的朋友作为 ...

  4. 用localStorage实现登录时记住密码的功能

    用localStorage实现登录时记住密码的功能 HTNL代码片段 <el-input v-model="ruleForm.user" placeholder=" ...

  5. ASP实现记住密码的功能

    把以下代码加入验证页:  <%if Trim(Cstr(request.QueryString("check")))="true" then '用来判断是 ...

  6. Cookie和Session实现记住我的功能

    Cookie和Session都是用来保存用户的一些信息的,但是由于Cookie保存在浏览器中,所以相对不安全,后来就出现了Session,Session呢是保存在服务器端的,所以相对安全,在Cooki ...

  7. C#-WinForm登录窗体实现记住密码的功能(仿QQ实现)

    背景 Winform实现登录窗体中记住密码的功能,模仿QQ登录记住密码的实现 如下图所示,其中标题部分因为项目保密的原因,我加了马赛克,请大家见谅. 用户名输入框我们采用下拉列表框ComboBox 密 ...

  8. 实现类似QQ记住密码的功能

    记住用户的密码,一般浏览器都有这个功能,基于C/S结构的软件实现这个功能也有很多方法,这里采用简单的文件流保存用户名及密码的方法来实现这个功能. Person类,模拟用户 using System; ...

  9. Apache使用mod_deflate模块启用gzip功能

    Apache使用mod_deflate模块启用gzip功能 检查你的网站是否启用了gzip,用chrome打开网站比如http://www.techbrood.com 选中一个请求,查看Respons ...

最新文章

  1. 实战SSM_O2O商铺_14【商铺注册】View层之验证码kaptcha组件
  2. 对软件体系结构的认识
  3. 【Centos 8】【Centos 7】【Docker】 安装 RabbitMQ
  4. 关于DubboMain启动的真相
  5. 沃信科技ERP系统容灾方案概述
  6. 一些图形学中的数学应用
  7. qt先生成json文件后程序启动时读取json文件在一组数据模拟下正常,换一组数据就出现乱码
  8. Delphi clientdataset的详细介绍
  9. python爬虫(8)--Xpath语法与lxml库
  10. python如何处理spark上的数据_Pyspark获取并处理RDD数据代码实例
  11. 快速排序多种方法代码Python
  12. XCTest+XCTool
  13. Win7系统开机动画设置
  14. 关于Android的ImageView置顶
  15. 云计算与虚拟化的关系是什么?
  16. 数据库和SpringBoot
  17. OpenHarmony命令行工具hdc_std使用总结
  18. yii mysql gii_yii框架之gii的使用
  19. Unity 实现回血效果
  20. python 读视频_Python3读取视频保存视频

热门文章

  1. Java命令学习系列(一)——Jps
  2. (C语言)请编写程序,计算1-1/2-1/3-1/4-.....-1/50的和。
  3. sh(Spring+Spring mvc+hibernate)——IDeptDao.java
  4. 让浏览器认为现在处于登录状态
  5. 控制台查出数据传到layui数据表格却没有数据的问题
  6. micrometer_具有InlfuxDB的Spring Boot和Micrometer第2部分:添加InfluxDB
  7. java编程学习方法_在线学习Java编程的最佳方法
  8. 在Selenium中按TagName定位元素
  9. jdk 流合并_JDK 12,合并的收集器和命名的挑战
  10. 用jackson转json_用Jackson编写大JSON文件