项目源码

国涛/springboot-shiro-jwthttps://gitee.com/dugt/springboot-shiro-jwt

GitHub - dugt-1998/springboot-shiro-jwt: 杜国涛的仓库杜国涛的仓库. Contribute to dugt-1998/springboot-shiro-jwt development by creating an account on GitHub.https://github.com/dugt-1998/springboot-shiro-jwt

核心部分

授权 认证

首先定义我们的配置类

/*** <p>* shiro核心配置类* </p>** @author duguotao* @version 1.0.0* @since Created in 2021/11/11*/
@Configuration
public class ShiroConfig {/*** 先经过token过滤器,如果检测到请求头存在 token,则用 token 去 login,接着走 Realm 去验证*/@Beanpublic ShiroFilterFactoryBean factory(SecurityManager securityManager) {ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();Map<String, Filter> filterMap = new LinkedHashMap<>();//设置我们自定义的JWT过滤器filterMap.put("jwt", new JWTFilter());factoryBean.setFilters(filterMap);factoryBean.setSecurityManager(securityManager);factoryBean.setUnauthorizedUrl("/unauthorized/无权限");Map<String, String> filterRuleMap = new HashMap<>();// 所有请求通过我们自己的JWT FilterfilterRuleMap.put("/**", "jwt");//内置过滤器,可以实现权限相关的拦截器//  user:如果使用remember的功能才能直接访问//  perms:必须得到资源权限才可访问//  role:必须得到角色权限才可访问// 放行不需要权限认证的接口// swagger 静态资源 或websocket服务器链接接口 都可在此配置filterRuleMap.put("/login", "anon");filterRuleMap.put("/unauthorized/**", "anon");factoryBean.setFilterChainDefinitionMap(filterRuleMap);return factoryBean;}/*** 注入 securityManager*/@Beanpublic SecurityManager securityManager(UserRealm customRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 设置自定义 realm.securityManager.setRealm(customRealm);/** 关闭shiro自带的session*/DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();defaultSessionStorageEvaluator.setSessionStorageEnabled(false);subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);securityManager.setSubjectDAO(subjectDAO);return securityManager;}/*** 添加注解支持*/@Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();// 强制使用cglib,防止重复代理和可能引起代理出错的问题defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);return defaultAdvisorAutoProxyCreator;}@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}@Beanpublic LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}
}

自定义relam

/*** <p>* 自定义Realm, 实现Shiro安全认证* </p>** @author duguotao* @version 1.0.0* @since Created in 2021/11/11*/
@Component
@RequiredArgsConstructor
public class UserRealm extends AuthorizingRealm {final UserService userService;/*** 必须重写此方法,不然会报错*/@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof JWTToken;}/*** 认证*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {String token = (String) authenticationToken.getCredentials();// 解密获得username,用于和数据库进行对比String username = JWTUtil.getUsername(token);if (username == null || !JWTUtil.verify(token, username)) {throw new AuthenticationException("token认证失败或token已过期!");}userService.auth(username);return new SimpleAuthenticationInfo(token, token, "MyRealm");}/*** 授权*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String username = JWTUtil.getUsername(principals.toString());SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// 获得该用户角色String role = userService.getRole(username);// 用户拥有的权限List<String> permission = userService.getPermission(username);Set<String> roleSet = new HashSet<>();roleSet.add(role);Set<String> permissionSet = new HashSet<>(permission);//设置该用户拥有的角色和权限info.setRoles(roleSet);info.setStringPermissions(permissionSet);return info;}
}

目前常用开发架构前后端分离,前后端分离项目就不能采用之前的cookie而是现在的token方式

jwt对token的认证还是不错的

首先定义jwt过滤器继承 BasicHttpAuthenticationFilter 通过header中的token信息作处理

/*** <p>* 自定义过滤器 对token相关操作* </p>** @author duguotao* @version 1.0.0* @since Created in 2021/11/11*/
public class JWTFilter extends BasicHttpAuthenticationFilter {private final Logger logger = LoggerFactory.getLogger(this.getClass());private static final String TOKEN = "token";/*** 校验token*/@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {if (!isLoginAttempt(request, response)) {return false;}try {executeLogin(request, response);return true;} catch (Exception e) {//token 错误responseError(response, e.getMessage());return false;}}/*** 判断用户是否想要登入。* 检测 header 里面是否包含 token 字段*/@Overrideprotected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {HttpServletRequest req = (HttpServletRequest) request;String token = req.getHeader(TOKEN);return token != null;}/*** 执行登陆操作*/@Overrideprotected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {HttpServletRequest httpServletRequest = (HttpServletRequest) request;String token = httpServletRequest.getHeader(TOKEN);JWTToken jwtToken = new JWTToken(token);// 提交给realm进行登入,如果错误它会抛出异常并被捕获getSubject(request, response).login(jwtToken);// 如果没有抛出异常则代表登入成功,返回truereturn true;}/*** 对跨域提供支持*/@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {httpServletResponse.setStatus(HttpStatus.OK.value());return false;}return super.preHandle(request, response);}/*** 将非法请求跳转到 /unauthorized/***/private void responseError(ServletResponse response, String message) {try {HttpServletResponse httpServletResponse = (HttpServletResponse) response;//设置编码,否则中文字符在重定向时会变为空字符串message = URLEncoder.encode(message, "UTF-8");httpServletResponse.sendRedirect("/unauthorized/" + message);} catch (IOException e) {logger.error(e.getMessage());}}
}

测试代码

/*** <p>* 测试一下* </p>** @author duguotao* @version 1.0.0* @since Created in 2021/11/11*/
@RestController
@RequiredArgsConstructor
public class UserController {final UserService userService;final HttpServletRequest httpServletRequest;@GetMapping("/login")public JsonResult<String> login(String username, String password) {userService.login(username, password);return JsonResult.OK(JWTUtil.createToken(username));}// -------------- 权限注解 ----------------@GetMapping("/getM1")@RequiresPermissions(value = "perm:hello")public JsonResult<String> getM1() {return JsonResult.OK("hello word");}@GetMapping("/getM2")@RequiresPermissions(value = {"perm:hello", "perm:test"}, logical = Logical.OR)public JsonResult<String> getM2() {return JsonResult.OK("hello m2");}// -------------- 角色注解 ----------------@GetMapping("/getM3")@RequiresRoles(value = "admin")public JsonResult<String> getM3() {return JsonResult.OK("hello m3");}@GetMapping("/getM4")@RequiresRoles(value = {"admin", "emp"}, logical = Logical.OR)public JsonResult<String> getM4() {return JsonResult.OK("hello m4");}
}

前后端分离 springboot shiro+jwt token认证 权限校验相关推荐

  1. 前后端分离session_前后端分离:基于JWT用户认证分析

    作者:lion1ou https://lion1ou.win/2017/01/18/ 在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们 ...

  2. 前后端分离(SpringBoot+Vue)-基础的权限管理系统

    前后端分离(SpringBoot+Vue)-基础的权限管理系统 简介 前端项目代码地址:前端代码 后端项目代码地址:后端代码 最后的附录记录了自己在开发过程遇到问题及实现.部分文件的介绍 采用前后端分 ...

  3. SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(二)

    关注公众号[江南一点雨],专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货! 当前后端分离时,权限问题的 ...

  4. SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(六)

    当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案 ...

  5. boke | 前后端分离中使用JWT保持前端数据的持久化,并自动登录

    在boke后台登录系统中实现了自动登录的功能,这也是前后端分离的开发模式中最常见的一个问题,如何保持登录状态的持久化.今天就来通过实现自动登录来一步步理清前端数据持久化的思路. 一 实现思路 当用户首 ...

  6. 网易音乐网站系统|前后端分离springboot+vue实现在线音乐网站

    作者主页:编程千纸鹤 作者简介:Java.前端.Python开发多年,做过高程,项目经理,架构师 主要内容:Java项目开发.毕业设计开发.面试技术整理.最新技术分享 收藏点赞不迷路  关注作者有好处 ...

  7. SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(一)

    当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案 ...

  8. 前后端分离报错The Token’s Signature resulted invalid when verified using the Algorithm: HmacSHA256

    框架spring boot+shiro+jwt.验证token的时候报错如标题,经检查发现,前端传的token是 "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. ...

  9. springboot+shiro+jwt实现登录+权限验证

    目录 一.简介: JWT优点: JWT缺点: shiro: JWT: 1.JWT头 2.有效载荷 3.签名哈希 4.Base64URL算法 二.实现 1.引入maven依赖 2.编写shiro配置类 ...

最新文章

  1. React 教程:快速上手指南
  2. 【090723】动态调用webservice
  3. OpenGL抗锯齿实例
  4. Windows 11 大更新!可安装超千款 Android 应用
  5. 新一代Notebook神器出现,Jupyter危险了!
  6. Python—实训day12—汽车用户消费投诉案例-分析及可视化
  7. SharePoint学习札记[5] — 设置匿名访问
  8. android camera2 采集,视频采集:Android平台基于Camera 2的实现
  9. 花钱你都学不到的“饭局”规矩~
  10. mysql 5.7配置的一些记录
  11. linux shell脚本教程
  12. java中stringBuilder的用法(转)
  13. “33岁,阿里程序员,税后年薪170万,我征婚有要求,有错吗?”
  14. java 指令发送短信_Java短信发送机的实现
  15. python对数据分组的方法
  16. keytool命令整理
  17. 二叉树:表达式二叉树转换成中缀式(括弧处理)
  18. 巧妙隐藏Word文档中指定文字内容
  19. <UDP网络编程>——《计算机网络》
  20. 复杂网络中衡量网络中节点中心性的几种度量指标

热门文章

  1. 微信开放平台全网发布
  2. C陷阱与缺陷 第2章 语法“陷阱” 2.6 “悬挂”else引发的问题
  3. 6个座位办公室最佳位置_办公室座位风水
  4. 【转】百度编辑器UEditor
  5. 编辑器之神——vim编辑器(详细、完整)
  6. 使用 Navicat 和强化AI的查询
  7. CentOS下架设VNC服务器
  8. java中equals的反义词_equals是什么意思_equals怎么读_equals翻译_用法_发音_词组_同反义词_同样的人( equal的名词复数 )-新东方在线英语词典...
  9. Jetson TX1板载相机调用测试
  10. 【免费分享】让思路更清晰,思维导图教程及工具