springboot整合shiro实现记住我功能

网友投稿 297 2022-09-20


springboot整合shiro实现记住我功能

前言

上一篇 文章我们完成了在 thymeleaf 模板引擎中使用 shiro 标签,也就是根据不同的用户身份信息,前端页面来显示不同的页面内容。本篇文章我们来完成在登录页面的记住我的功能

springboot 整合 shiro 之实现记住我

项目依然使用 springboot整合shiro 这个项目,稍稍改动即可完成记住我的功能

配置类 ShiroConfig

完整的代码如下

@Configuration

puhttp://blic class ShiroConfig {

/**

* 安全管理器

*

* @param userRealm userRealm

* @return defaultWebSecurityManager

*/

@Bean

public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {

DefaultWebSecurityManager defaultWebSecurityManager = new iMpIQrPNBDefaultWebSecurityManager();

defaultWebSecurityManager.setRealm(userRealm);

// 实现记住我,所需要的配置

defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager());

return defaultWebSecurityManager;

}

/**

* thymeleaf模板引擎中使用shiro标签时,要用到

*

* @return

*/

@Bean

public ShiroDialect getShiroDialect() {

return new ShiroDialect();

}

@Bean

public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager defaultWebSecurityManager) {

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

// 设置登录页面url

shiroFilterFactoryBean.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这个url

filterChainDefinitionMap.put("/user/add", "perms[user:add]");

filterChainDefinitionMap.put("/user/update", "perms[user:update]");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

return shiroFilterFactoryBean;

}

// 实现记住我,所需要的配置

@Bean

public SimpleCookie simpleCookie() {

// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe

SimpleCookie simpleCookie = new SimpleCookie("rememberMe");

simpleCookie.setHttpOnly(true);

// 记住我cookie生效时间1小时,单位秒

simpleCookie.setMaxAge(60 * 60);

return simpleCookie;

}

// 实现记住我,所需要的配置

@Bean

public 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")

@Slf4j

public 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")

@ResponseBody

public 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);

}

// 将用户名,密码交给shiro

UsernamePasswordToken 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 为例进行登录,如下

进入首页页面如下,再次查看 Cookies 数据

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

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

说明账号 jack 没有权限访问 update.html 页面,可以看控制台 sql 日志

源码:springboot-shiro


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:NAT网络地址转换及配置命令
下一篇:# 聊一聊悟空编辑器 #15、华为无线STA黑白名单的应用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~