马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

Spring Security 整合JWT(四)

[复制链接]
查看2177 | 回复1 | 2019-10-24 09:50:31 | 显示全部楼层 |阅读模式

一、前言

本篇文章将报告Spring Security 简单整合JWT 处理认证授权

根本环境
  1. spring-boot 2.1.8
  2. mybatis-plus 2.2.0
  3. mysql 数据库
  4. maven项目
Spring Security入门学习可参考之前文章:
  1. SpringBoot集成Spring Security入门体验(一)
    https://blog.csdn.net/qq_38225558/article/details/101754743
  2. Spring Security 自定义登录认证(二)
    https://blog.csdn.net/qq_38225558/article/details/102542072
  3. Spring Security 动态url权限控制(三)
    https://blog.csdn.net/qq_38225558/article/details/102637637

二、 Spring Security 简单整合 JWT

有关JWT不了解的可以看下官网文档:https://jwt.io/introduction/

095031s3x078zi1q00wf4c.png

1、引入jwt依赖

  1. <code> <!-- jwt依赖: https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
  2. <dependency>
  3. <groupId>io.jsonwebtoken</groupId>
  4. <artifactId>jjwt</artifactId>
  5. <version>0.9.1</version>
  6. </dependency></code>
复制代码

2、在Security登录认证乐成后生成jwt令牌返回给前端生存

jwt生成令牌代码如下:

  1. <code>// 生成jwt访问令牌
  2. String jwtToken = Jwts.builder()
  3. // 用户脚色
  4. .claim("ROLE_LOGIN", "ADMIN")
  5. // 主题 - 存用户名
  6. .setSubject("张三")
  7. // 逾期时间 - 30分钟
  8. .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
  9. // 加密算法和密钥
  10. .signWith(SignatureAlgorithm.HS512, "helloworld")
  11. .compact();</code>
复制代码

这里贴出小编文末案例demo源码中关于登录认证处理中的使用

  1. <code>@Component
  2. public class AdminAuthenticationProvider implements AuthenticationProvider {
  3. @Autowired
  4. UserDetailsServiceImpl userDetailsService;
  5. @Autowired
  6. private UserMapper userMapper;
  7. @Override
  8. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  9. // 获取前端表单中输入后返回的用户名、密码
  10. String userName = (String) authentication.getPrincipal();
  11. String password = (String) authentication.getCredentials();
  12. SecurityUser userInfo = (SecurityUser) userDetailsService.loadUserByUsername(userName);
  13. boolean isValid = PasswordUtils.isValidPassword(password, userInfo.getPassword(), userInfo.getCurrentUserInfo().getSalt());
  14. // 验证密码
  15. if (!isValid) {
  16. throw new BadCredentialsException("密码错误!");
  17. }
  18. // 前后端分离环境下 处理逻辑...
  19. // 更新登录令牌
  20. // 当前用户所拥有脚色代码
  21. String roleCodes = userInfo.getRoleCodes();
  22. // 生成jwt访问令牌
  23. String jwt = Jwts.builder()
  24. // 用户脚色
  25. .claim(Constants.ROLE_LOGIN, roleCodes)
  26. // 主题 - 存用户名
  27. .setSubject(authentication.getName())
  28. // 逾期时间 - 30分钟
  29. .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
  30. // 加密算法和密钥
  31. .signWith(SignatureAlgorithm.HS512, Constants.SALT)
  32. .compact();
  33. User user = userMapper.selectById(userInfo.getCurrentUserInfo().getId());
  34. user.setToken(jwt);
  35. userMapper.updateById(user);
  36. userInfo.getCurrentUserInfo().setToken(jwt);
  37. return new UsernamePasswordAuthenticationToken(userInfo, password, userInfo.getAuthorities());
  38. }
  39. @Override
  40. public boolean supports(Class<?> aClass) {
  41. return true;
  42. }
  43. }</code>
复制代码

前端页面生存的jwt令牌格式如下:

095032ayuu4y6q5u5y62u5.png

3、Security访问鉴权中认证用户信息

我们在访问每一个url请求的时间,在同一认证的地方获取jwt中我们必要的信息然后认证即可,【注: Claims 中存放着我们必要的信息】
比方: 我们可以将用户名、密码存放jwt中,然后在认证的时间读取到此中的用户信息,然后查询数据库认证用户,假如满意条件即乐成访问,假如不满意条件即抛出非常处理

温馨小提示:假如jwt令牌逾期,会抛出ExpiredJwtException非常,我们必要拦截到,然后交给认证失败处理器中处理,然后返回给前端,这里根据个人业务实际处理即可~

  1. <code>// 获取jwt中的信息
  2. Claims claims = Jwts.parser().setSigningKey("helloworld").parseClaimsJws(jwtToken.replace("Bearer", "")).getBody();
  3. // 获取当前登录用户名
  4. System.out.println("获取当前登录用户名: " + claims.getSubject());</code>
复制代码

小编项目中认证过滤器中的使用如下:

  1. <code>@Slf4j
  2. @Component
  3. public class MyAuthenticationFilter extends OncePerRequestFilter {
  4. @Autowired
  5. AdminAuthenticationEntryPoint authenticationEntryPoint;
  6. private final UserDetailsServiceImpl userDetailsService;
  7. protected MyAuthenticationFilter(UserDetailsServiceImpl userDetailsService) {
  8. this.userDetailsService = userDetailsService;
  9. }
  10. @Override
  11. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  12. MultiReadHttpServletRequest wrappedRequest = new MultiReadHttpServletRequest(request);
  13. MultiReadHttpServletResponse wrappedResponse = new MultiReadHttpServletResponse(response);
  14. StopWatch stopWatch = new StopWatch();
  15. try {
  16. stopWatch.start();
  17. // 前后端分离环境下,前端登录后将token储存在cookie中,每次访问接口时通过token去拿用户权限
  18. String jwtToken = wrappedRequest.getHeader(Constants.REQUEST_HEADER);
  19. log.debug("背景查抄令牌:{}", jwtToken);
  20. if (StringUtils.isNotBlank(jwtToken)) {
  21. // JWT干系start ===========================================
  22. // 获取jwt中的信息
  23. Claims claims = Jwts.parser().setSigningKey(Constants.SALT).parseClaimsJws(jwtToken.replace("Bearer", "")).getBody();
  24. // 获取当前登录用户名
  25. System.out.println("获取当前登录用户名: " + claims.getSubject());
  26. // TODO 如需使用jwt特性在此做处理~
  27. // JWT干系end ===========================================
  28. // 查抄token
  29. SecurityUser securityUser = userDetailsService.getUserByToken(jwtToken);
  30. if (securityUser == null || securityUser.getCurrentUserInfo() == null) {
  31. throw new BadCredentialsException("TOKEN已逾期,请重新登录!");
  32. }
  33. UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());
  34. // 全局注入脚色权限信息和登录用户根本信息
  35. SecurityContextHolder.getContext().setAuthentication(authentication);
  36. }
  37. filterChain.doFilter(wrappedRequest, wrappedResponse);
  38. } catch (ExpiredJwtException e) {
  39. // jwt令牌逾期
  40. SecurityContextHolder.clearContext();
  41. this.authenticationEntryPoint.commence(wrappedRequest, response, null);
  42. } catch (AuthenticationException e) {
  43. SecurityContextHolder.clearContext();
  44. this.authenticationEntryPoint.commence(wrappedRequest, response, e);
  45. } finally {
  46. stopWatch.stop();
  47. }
  48. }
  49. }</code>
复制代码

简单的入门使用就是这样了

三、总结

  1. 引入jwt依赖
  2. 登录体系乐成后生成jwt令牌返回给前端生存到欣赏器请求头
  3. 在每一次请求访问体系url时,在同一认证过滤器中获取到请求头中jwt令牌中生存的用户信息然后做认证处理,假如满意条件乐成访问,假如不满意交给认证失败处理器返回指定内容给前端

本文案例demo源码

https://gitee.com/zhengqingya/java-workspace







来源:https://www.cnblogs.com/zhengqing/p/11726855.html
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则