1.什么是remeber-me?

remeber-me即记住我功能,是我们在登录web系统时的常见勾选项。当我们登录一个web系统时除了输入常规的用户名、密码后还可以勾选记住我选项(假设该系统提供了该选项),此时假设用户名、密码输入正确那么系统将会在客户浏览器cookie中记录用户登录相关认证相关信息。实现的效果就是当我们下次再次访问该网站某些页面时无需再次登录。

2.rember-me实现原理

2.1 登录过程中记住我流程:

2.2 直接访问系统目标页,服务端验证流程:

2.3 退出流程

删除cookie,销毁session。

3.使用springboot实现步骤

本文为了快速演示记住我功能将采取服务端硬编码方式代替数据库存储,表达的原理一致就Ok。

只列出关键部分代码,详细请看文章结尾源码链接查看完整代码。

3.1 创建用户模型

@Data
public class SysUser {
private String username;
private String password;
private Integer rememberMe;
}

3.2 创建登录控制器

@Controller
@Slf4j
public class LoginController {
@RequestMapping("/login")
public String loginPage(){
return "login";
} @RequestMapping("/index")
public String index(){
return "index";
} @PostMapping("/dologin")
public String login(SysUser user,
HttpServletRequest request,
HttpServletResponse response,
Model model){
// 判断用户名密码
if(!("admin".equals(user.getUsername()) && "admin".equals(user.getPassword()))){
return "redirect:login";
} // 认证成功,向session中添加用户信息
HttpSession session = request.getSession();
session.setAttribute("user",user); // 判断是否勾选了记住我
if(user.getRememberMe()!=null){
// 为了演示方便token写死,为用户名:admin的base64编码
Cookie cookie = new Cookie("boot_rememberMe", "YWRtaW4=");
// 为了演示设置cookie过期时间为30s
cookie.setMaxAge(30);
response.addCookie(cookie);
} return "redirect:index";
} @GetMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
if (null == session || session.getAttribute("user") == null) {
return "login";
}
session.invalidate();
Cookie[] cookies = request.getCookies();
if (ObjectUtils.isEmpty(cookies)) { } else {
for (Cookie cookie : cookies) {
String name = cookie.getName();
if (name.equals("boot_rememberMe")) {
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
} return "login"; }
}

3.3 创建RememberFilter

@Slf4j
@Component
public class RememberFilter implements Filter {
private String[] noFilterArray=new String[]{"/login","/dologin"}; @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
List<String> noFilterList= Arrays.asList(noFilterArray);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String requestURI = req.getRequestURI();
requestURI = requestURI.substring(requestURI.lastIndexOf("/"));
// 判断是否为不需要过滤请求
if (noFilterList.contains(requestURI)) {
filterChain.doFilter(request,response);
}else{
HttpSession session = req.getSession();
if (null==session||session.getAttribute("user")==null) {
Cookie[] cookies = req.getCookies();
if (ObjectUtils.isEmpty(cookies)) {
((HttpServletResponse) response).sendRedirect(req.getContextPath()+"/login");
return;
} else {
SysUser user = null;
for(Cookie cookie:cookies){
String name = cookie.getName();
if (name.equals("boot_rememberMe")) {
String value = cookie.getValue();
// 演示采用硬编码,实际需要和数据库中token比较
if (!value.equals("YWRtaW4=")) {
Cookie cookie1=new Cookie("boot_rememberMe",null);
cookie1.setMaxAge(0);
res.addCookie(cookie1);
}else{
user = new SysUser();
user.setUsername("admin");
user.setPassword("admin");
user.setRememberMe(1);
session.setAttribute("user", user);
log.info("从cookie中获取user放入session");
}
}
}
if(user==null){
((HttpServletResponse) response).sendRedirect(req.getContextPath()+"/login");
return;
}
}
}
filterChain.doFilter(request,response);
} }
}

3.4 创建登录页

<form action="/dologin" method="post" th:action="@{/dologin}">
<div class="title">
<h1>后台管理系统</h1>
</div>
<div class="form-item">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" />
</div>
<div class="form-item">
<label for="password">密码:</label>
<input type="text" id="password" name="password" />
</div>
<div class="form-item">
<input type="checkbox" id="rememberMe" name="rememberMe" value="1"/>记住我
<input type="checkbox" name="rememberMe" hidden="hidden">
</div>
<div class="form-item">
<button type="submit" id="submit" class="btn btn-primary">
登录
</button>
</div>
</form>

3.5 创建首页

<body>
欢迎,<span th:text="${session.user.username}"></span>
<a href="" th:href="@{/logout}">退出</a>
</body>

4.测试

输入地址:localhost:9000/login,用户名:admin,密码:admin

4.1 不勾选记住我

不勾选就是简单的登录退出功能。

4.2 勾选记住我

  • 成功登陆后,关闭浏览器
  • 30s内再次打开浏览器输入首页地址发现可以直接访问
  • 30s后再次访问首页发现cookie失效直接跳转到登录页
  • 退出后cookie失效,无法再次访问首页

4.3 相关截图


  • 首页

5.项目代码

https://gitee.com/indexman/boot_rememberme/tree/master/

Springboot实现remember-me记住我功能的更多相关文章

  1. SpringBoot + Spring Security 学习笔记(四)记住我功能实现

    记住我功能的基本原理 当用户登录发起认证请求时,会通过UsernamePasswordAuthenticationFilter进行用户认证,认证成功之后,SpringSecurity 调用前期配置好的 ...

  2. Spring Security框架下实现两周内自动登录"记住我"功能

    本文是Spring Security系列中的一篇.在上一篇文章中,我们通过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户.角色.权限相关信息,从而实 ...

  3. java实现记住密码功能(利用cookie)

    <br> <input type="text" id="userName" name="userName" value=& ...

  4. 通过sharedpreferences实现记住密码功能

    通过sharedpreferences实现记住密码功能

  5. jquery.cookie.js 操作cookie实现记住密码功能的实现代码

    jquery.cookie.js操作cookie实现记住密码功能,很简单很强大,喜欢的朋友可以参考下.   复制代码代码如下: //初始化页面时验证是否记住了密码 $(document).ready( ...

  6. cookie记住密码功能

    很多门户网站都提供了记住密码功能,虽然现在的浏览器都已经提供了相应的记住密码功能 效果就是你每次进入登录页面后就不需要再进行用户名和密码的输入: 记住密码功能基本都是使用cookie来进行实现的,因此 ...

  7. 【原创】js中利用cookie实现记住密码功能

    在登录界面添加记住密码功能,我首先想到的是在java后台中调用cookie存放账号密码,大致如下: HttpServletRequest request HttpServletResponse res ...

  8. android: SharedPreferences实现记住密码功能

    既然是实现记住密码的功能,那么我们就不需要从头去写了,因为在上一章中的最佳实 践部分已经编写过一个登录界面了,有可以重用的代码为什么不用呢?那就首先打开 BroadcastBestPractice 项 ...

  9. asp.net记住我功能

    登录页面的记住我功能   不能用session的原因:sessionID是以cookie的形式存在浏览器端的内存中  如果用户把浏览器关闭 则sessionID就消失     但是服务器端的sessi ...

  10. vue项目实现记住密码功能

     一.谷歌浏览的残留问题 现在很多的网站都有一个需求是记住密码这个功能,为的是避免用户下次登录的时候繁琐的输入过程. 像是一些主流的浏览器(比如Chrome)都有了这个功能,而且如果你登录了Chrom ...

随机推荐

  1. java - 递归排序 - 求数组最小值

    // 递归求数组最小值 public class Bubble { // 定义存储最小值的变量 static int min; public static void main(String[] arg ...

  2. 让vs自动提示没有using的类

    默认情况下,没有using的类,敲代码时没有智能提示,需要在[工具]->[选项]中开启

  3. [转帖]查看mysql分区名和各分区数据量

    – 查看mysql分区名和各分区数据量 SELECT table_name, partition_name, table_rows FROM information_schema.PARTITIONS ...

  4. [转帖]数据可视化之redash(支持43种数据源) (转自https://anjia0532.github.io/2019/07/08/redash/)

    https://www.cnblogs.com/a00ium/p/13177272.html 人类都是视觉动物,讲究一图胜千言.如果没了可视化,那么你在跟领导汇报工作时,很大程度会鸡同鸭讲.其实 ex ...

  5. Oracle 设置白名单过滤

    最近有一个需求  要求开发人员不能随便连接测试的数据库 又不想太过复杂,部分人还得进行连结. 查了下往上是有方案的: 就是 TCP_VALIDNODE_CHECKING 参数 解决方法和说明如下 来源 ...

  6. 基于Apache PDFBox的PDF数字签名

    在Java语言环境中完成数字签名主要基于itext-pdf.PDFBox两种工具,itext-pdf受商业限制,应用于商业服务中需要购买授权.PDFBox是apache基金会开源项目,基于apache ...

  7. css3中的圆角border-radius

    css3的属性应该加上浏览器前缀 不同的浏览器内核不同,因此css的前缀不同. 常见的几种浏览器内核 火狐浏览器 Geoko内核 前缀是 -mox- 谷歌浏览器, Webkit内核 前缀是 -wekb ...

  8. void的讲解 、any的讲解 、联合类型的讲解

    1. void的使用 空值一般采用 void 来表示,同时void也可以表示变量 也可以表示函数没有返回值哈 使用了 void 就不能够使用 return 哈 let sum = function() ...

  9. css 动画 div顺时针方向移动,

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Gorm 入门介绍与基本使用

    Gorm 入门介绍与基本使用 目录 Gorm 入门介绍与基本使用 一.ORM简介 1.1 什么是ORM 1.2 使用ORM的好处 1.2.1 避免直接操作SQL语句 1.2.2 提高代码的可维护性 1 ...