springboot整合shiro实现记住我功能

前言 上一篇 文章我们完成了在 thymeleaf 模板引擎中使用 shiro 标签,也就是根据不同的用户身份信息,前端页面来显示不同的页面内容。本篇文章我们来完成在登录页面的记住我的功能
springboot 整合 shiro 之实现记住我 项目依然使用 springboot整合shiro 这个项目,稍稍改动即可完成记住我的功能
配置类 ShiroConfig
完整的代码如下

@Configurationpublic class ShiroConfig {/*** 安全管理器** @param userRealm userRealm* @return defaultWebSecurityManager*/@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(userRealm); // 实现记住我,所需要的配置defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager()); return defaultWebSecurityManager; }/*** thymeleaf模板引擎中使用shiro标签时,要用到** @return*/@Beanpublic ShiroDialect getShiroDialect() {return new ShiroDialect(); }@Beanpublic ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); // 设置登录页面urlshiroFilterFactoryBean.setLoginUrl("/user/login"); shiroFilterFactoryBean.setSuccessUrl("/user/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauthorized"); // 注意此处使用的是LinkedHashMap是有顺序的,shiro会按从上到下的顺序匹配验证,匹配了就不再继续验证Map filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/layer/**", "anon"); // 静态资源放行filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/jquery/**", "anon"); // add.html页面放行filterChainDefinitionMap.put("/user/add", "authc"); // update.html必须认证filterChainDefinitionMap.put("/user/update", "authc"); // index.html必须认证filterChainDefinitionMap.put("/user/index", "user"); // 设置授权,只有user:add权限的才能请求/user/add这个urlfilterChainDefinitionMap.put("/user/add", "perms[user:add]"); filterChainDefinitionMap.put("/user/update", "perms[user:update]"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } // 实现记住我,所需要的配置@Beanpublic SimpleCookie simpleCookie() {// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMeSimpleCookie simpleCookie = new SimpleCookie("rememberMe"); simpleCookie.setHttpOnly(true); // 记住我cookie生效时间1小时,单位秒simpleCookie.setMaxAge(60 * 60); return simpleCookie; } // 实现记住我,所需要的配置@Beanpublic CookieRememberMeManager cookieRememberMeManager() {CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(simpleCookie()); // rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag==")); return cookieRememberMeManager; }}

login.html 登录页面
此时要拿到复选框 checkbox 是否被用户选中的状态值,选中为 true,未选中为 false,将这个状态值发生至后端登录接口
登录
账号:
密码:
记住我


controller
@Controller@RequestMapping(path = "/user")@Slf4jpublic class UserController {@GetMapping(path = "/login")public String login() {return "login"; }@GetMapping(path = "/index")public String index() {return "index"; }@GetMapping(path = "/add")public String add() {return "add"; }@GetMapping(path = "/update")public String update() {return "update"; }@GetMapping(path = "/unauthorized")public String unauthorized() {return "unauthorized"; }/*** 用户登录** @param userVO* @param bindingResult* @return*/@PostMapping(path = "/doLogin")@ResponseBodypublic ResultMap doLogin(@NotNull @Valid UserVO userVO, @NotNull BindingResult bindingResult) {// ------参数校验------if (bindingResult.hasErrors()) {String message = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage(); log.info("校验的message信息为:" + message); return new ResultMap().fail().message(message); }// 将用户名,密码交给shiroUsernamePasswordToken token = new UsernamePasswordToken(userVO.getUsername(), userVO.getPassword(), userVO.getRememberMe()); String msg; try {// shiro帮我们匹配密码什么的,我们只需要把东西传给它,它会根据我们在UserRealm里认证方法设置的来验证Subject subject = SecurityUtils.getSubject(); subject.login(token); return new ResultMap().success().action("/user/index"); } catch (AuthenticationException e) {if (e instanceof IncorrectCredentialsException) {msg = "密码错误"; } else if (e instanceof LockedAccountException) {msg = "用户被禁用"; } else if (e instanceof UnknownAccountException) {msg = "用户不存在"; } else {msg = "用户认证失败"; }}return new ResultMap().error().message(msg); }/*** 用户退出登录* 添加记住我功能了,退出登录时,除了要当前的subject退出之外,还要删除用户浏览器上的Cookie信息** @return*/@GetMapping(path = "/logout")public String logout(HttpServletResponse response) {Subject subject = SecurityUtils.getSubject(); if (subject.isAuthenticated()) {subject.logout(); Cookie cookie = new Cookie("rememberMe", null); cookie.setMaxAge(0); response.addCookie(cookie); }return "login"; }}

UserVO
public class UserVO implements Serializable {@NotBlank(message = "账号不能为空")private String username; @NotEmpty(message = "密码不能为空")private String password; private Boolean rememberMe; // 省略set/get方法}

测试
我们以账号 jack 为例进行登录,如下
springboot整合shiro实现记住我功能
文章图片

进入首页页面如下,再次查看 Cookies 数据
springboot整合shiro实现记住我功能
文章图片

我们这时关闭这个首页页面,在浏览器地址栏输入 http://127.0.0.1:8080/user/index 再次进入首页页面,会发现如上图一样,可以顺利访问,说明我们的记住我功能已经实现。这时,可以再次在浏览器地址栏输入 http://127.0.0.1:8080/user/add,进入 add.html 页面,如下
springboot整合shiro实现记住我功能
文章图片


【springboot整合shiro实现记住我功能】Cookies 的有效期内,当你关闭浏览器之后,再次进入 add.html 页面时,无需登录直接就可以访问了,说明记住我功能已经实现了。在浏览器地址栏输入 http://127.0.0.1:8080/user/update,进入 update.html 页面,如下
springboot整合shiro实现记住我功能
文章图片

说明账号 jack 没有权限访问 update.html 页面,可以看控制台 sql 日志
springboot整合shiro实现记住我功能
文章图片

源码:springboot-shiro
到此这篇关于springboot整合shiro之实现记住我的文章就介绍到这了,更多相关springboot整合shiro之实现记住我内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读