SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期 (3)

在ShiroConfig中添加对会话管理器的配置

/** * SessionID生成器 * */ @Bean public ShiroSessionIdGenerator sessionIdGenerator(){ return new ShiroSessionIdGenerator(); } /** * 配置RedisSessionDAO */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); redisSessionDAO.setSessionIdGenerator(sessionIdGenerator()); redisSessionDAO.setKeyPrefix(SESSION_KEY); redisSessionDAO.setExpire(EXPIRE); return redisSessionDAO; } /** * 配置Session管理器 * @Author Sans * */ @Bean public SessionManager sessionManager() { ShiroSessionManager shiroSessionManager = new ShiroSessionManager(); shiroSessionManager.setSessionDAO(redisSessionDAO()); //禁用cookie shiroSessionManager.setSessionIdCookieEnabled(false); //禁用会话id重写 shiroSessionManager.setSessionIdUrlRewritingEnabled(false); return shiroSessionManager; }

目前最新版本(1.6.0)中,session管理器的setSessionIdUrlRewritingEnabled(false)配置没有生效,导致没有认证直接访问受保护资源出现多次重定向的错误。将shiro版本切换为1.5.0后就解决了这个bug。

本来这篇文章应该是昨晚发的,因为这个原因搞了好久,所有今天才发。。。

修改自定义Realm的doGetAuthenticationInfo认证方法

在认证信息返回前,我们需要做一个判断:如果当前用户已在旧设备上登录,则需要将旧设备上的会话id删掉,使其下线。

/** * 认证 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { if(token==null){ return null; } String principal = (String) token.getPrincipal(); User user = userService.findByUsername(principal); SimpleAuthenticationInfo simpleAuthenticationInfo = new MyAuthcInfo( //由于shiro-redis插件需要从这个属性中获取id作为redis的key //所有这里传的是user而不是username user, //凭证信息 user.getPassword(), //加密盐值 new CurrentSalt(user.getSalt()), getName()); //清除当前主体旧的会话,相当于你在新电脑上登录系统,把你之前在旧电脑上登录的会话挤下去 ShiroUtils.deleteCache(user.getUsername(),true); return simpleAuthenticationInfo; } 修改login接口

我们将会话信息存储在redis中,并在用户认证通过后将会话Id以token的形式返回给用户。用户请求受保护资源时带上这个token,我们根据token信息去redis中获取用户的权限信息,从而做访问控制。

@PostMapping("/login") public HashMap<Object, Object> login(@RequestBody LoginVO loginVO) throws AuthenticationException { boolean flags = authcService.login(loginVO); HashMap<Object, Object> map = new HashMap<>(3); if (flags){ Serializable id = SecurityUtils.getSubject().getSession().getId(); map.put("msg","登录成功"); map.put("token",id); return map; }else { return null; } } 添加全局异常处理 /**shiro异常处理 * @author 赖柄沣 bingfengdev@aliyun.com * @version 1.0 * @date 2020/10/7 18:01 */ @ControllerAdvice(basePackages = "pers.lbf.springbootshiro") public class AuthExceptionHandler { //==================认证异常====================http://www.likecs.com// @ExceptionHandler(ExpiredCredentialsException.class) @ResponseBody public String expiredCredentialsExceptionHandlerMethod(ExpiredCredentialsException e) { return "凭证已过期"; } @ExceptionHandler(IncorrectCredentialsException.class) @ResponseBody public String incorrectCredentialsExceptionHandlerMethod(IncorrectCredentialsException e) { return "用户名或密码错误"; } @ExceptionHandler(UnknownAccountException.class) @ResponseBody public String unknownAccountExceptionHandlerMethod(IncorrectCredentialsException e) { return "用户名或密码错误"; } @ExceptionHandler(LockedAccountException.class) @ResponseBody public String lockedAccountExceptionHandlerMethod(IncorrectCredentialsException e) { return "账户被锁定"; } //=================授权异常=====================http://www.likecs.com// @ExceptionHandler(UnauthorizedException.class) @ResponseBody public String unauthorizedExceptionHandlerMethod(UnauthorizedException e){ return "未授权!请联系管理员授权"; } }

实际开发中,应该对返回结果统一化,并给出业务错误码。这已经超出了本文的范畴,如有需要,请根据自身系统特点考量。

进行测试 认证

登录成功的情况

SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期

用户名或密码错误的情况

image-20201009130152368

为了安全起见,不要暴露具体是用户名错误还是密码错误。

访问受保护资源

认证后访问有权限的资源

image-20201009130937100

认证后访问无权限的资源

image-20201009131118464

未认证直接访问的情况

SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期

查看redis

image-20201009131904740

三个键值分别对应认证信息缓存、授权信息缓存和会话信息缓存。

写在最后

目前基本上把shiro的入门知识点学完了。国庆中秋小长假也结束了。后面有时间再补充shiro标签内容的使用。

最后贴出shiro的入门修仙功法链接,方便查看:

《走进shiro,构建安全的应用程序---shiro修仙序章》

《shiro认证流程源码分析--练气初期》

《Shiro入门学习---使用自定义Realm完成认证|练气中期》

《shiro入门学习--使用MD5和salt进行加密|练气后期》

《shiro入门学习--授权(Authorization)|筑基初期|》

《SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期》

如果您觉得这篇文章能给您带来帮助,那么可以点赞鼓励一下。如有错误之处,还请不吝赐教。在此,谢过各位乡亲父老!

代码及sql下载方式:微信搜索【Java开发实践】,加关注并回复20201009 即可获取下载链接。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyjpy.html