SpringBoot集成JWT

首先我们搭建好SpringBoot框架,SpringBoot环境准备就绪。接下来执行以下操作:

1.引入依赖

引入JWT依赖,由于是基于Java,所以需要的是java-jwt

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.5.0</version>
</dependency>

2.自定义注解

在这一步,我们在annotation包下定义一个用户需要登录才能进行其他接口访问等一系列操作的注解TokenRequired

`@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenRequired {boolean required() default true;
}

@Target旨意为我们自定义注解@TokenRequired的作用目标,因为我们本次注解的作用目标为方法层级,因此使用 ElementType.METHOD

@Retention旨意为我们自定义注解 @TokenRequired的保留位置,@TokenRequired的保留位置被定义为RetentionPolicy.RUNTIME这种类型的注解将被JVM保留,他能在运行时被JVM或其他使用反射机制的代码所读取和使用。

3.定义实体类

在entity包中,我们使用lombok,简单自定义一个实体类User。

`@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {String Id;String username;String password;
}

4.定义一个JWT工具类

在这一步,我们在util包下面创建一个JwtUtil工具类,用于生成token和校验token。

`public class JwtUtil {//过期时间15分钟private static final long EXPIRE_TIME = 15*60*1000;//生成签名,15分钟后过期public static String sign(String username,String userId,String password){//过期时间Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);//使用用户密码作为私钥进行加密Algorithm algorithm = Algorithm.HMAC256(password);//设置头信息HashMap<String, Object> header = new HashMap<>(2);header.put("typ", "JWT");header.put("alg", "HS256");//附带username和userID生成签名return JWT.create().withHeader(header).withClaim("userId",userId).withClaim("username",username).withExpiresAt(date).sign(algorithm);}//校验tokenpublic static boolean verity(String token,String password){try {Algorithm algorithm = Algorithm.HMAC256(password);JWTVerifier verifier = JWT.require(algorithm).build();verifier.verify(token);return true;} catch (IllegalArgumentException e) {return false;} catch (JWTVerificationException e) {return false;}}
}

5.业务校验并生成token

在service包下,我们创建一个UserService,并定义一个login方法,用于做登录接口的业务层数据校验,并调取JwtUtil中方法生成token。

`@Service("UserService")
public class UserService {@AutowiredUserMapper userMapper;public String login(String name, String password) {String token = null;try {//校验用户是否存在User user = userMapper.findByUsername(name);if(user == null){ResultDTO.failure(new ResultError(UserError.EMP_IS_NULL_EXIT));}else{//检验用户密码是否正确if(!user.getPassword().equals(password)){ResultDTO.failure(new ResultError(UserError.PASSWORD_OR_NAME_IS_ERROR));}else {// 生成token,将 user id 、userName保存到 token 里面token = JwtUtil.sign(user.getUsername(),user.getId(),user.getPassword());}}} catch (Exception e) {e.printStackTrace();}return token;}
}

Algorithm.HMAC256():使用HS256生成token,密钥则是用户的密码,唯一密钥的话可以保存在服务端。withAudience()存入需要保存在token的信息,这里我把用户ID存入token中。

6.定义拦截器

接下来我们需要写一个拦截器去获取token并验证token。

 `public class AuthenticationInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {// 从 http 请求头中取出 tokenString token = httpServletRequest.getHeader("token");// 如果不是映射到方法直接通过if(!(object instanceof HandlerMethod)){return true;}HandlerMethod handlerMethod=(HandlerMethod)object;Method method=handlerMethod.getMethod();//检查有没有需要用户权限的注解if (method.isAnnotationPresent(TokenRequired.class)) {TokenRequired userLoginToken = method.getAnnotation(TokenRequired.class);if (userLoginToken.required()) {// 执行认证if (token == null) {throw new RuntimeException("无token,请重新登录");}// 获取 token 中的 user idString userId;try {userId = JWT.decode(token).getClaim("userId").asString();} catch (JWTDecodeException j) {throw new RuntimeException("401");}User user = userService.findUserById(userId);if (user == null) {throw new RuntimeException("用户不存在,请重新登录");}// 验证 tokentry {if(!JwtUtil.verity(token,user.getPassword())){throw new RuntimeException("无效的令牌");}} catch (JWTVerificationException e) {throw new RuntimeException("401");}return true;}}return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}
}

AuthenticationInterceptor拦截器实现了HandlerInterceptor接口的三个方法:

  1. boolean preHandle ():

预处理回调方法,实现处理器的预处理,第三个参数为响应的处理器,自定义Controller返回值,返回值为true会调用下一个拦截器或处理器,或者接着执行postHandle()和afterCompletion();false表示流程中断,不会继续调用其他的拦截器或处理器,中断执行。

2.void postHandle():

后处理回调方法,实现处理器的后处理(DispatcherServlet进行视图返回渲染之前进行调用),此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理,modelAndView也可能为null。

3.void afterCompletion():

整个请求处理完毕回调方法,该方法也是需要当前对应的Interceptor的preHandle()的返回值为true时才会执行,也就是在DispatcherServlet渲染了对应的视图之后执行。用于进行资源清理。

该拦截器的执行流程为:

  1. 从 http 请求头中取出 token;
  2. 检查有没有需要用户权限的注解,如果需要,检验token是否为空;
  3. 如果token不为空,查询用户信息并校验token;
  4. 校验通过,则进行业务访问处理,校验失败则返回token失效信息。

7.配置拦截器

在配置类上添加了注解@Configuration,标明了该类是一个配置类并且会将该类作为一个SpringBean添加到IOC容器内。

`@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Beanpublic AuthenticationInterceptor authenticationInterceptor() {return new AuthenticationInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 将我们上步定义的实现了HandlerInterceptor接口的拦截器实例authenticationInterceptor添加InterceptorRegistration中,并设置过滤规则,所有请求都要经过authenticationInterceptor拦截。registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**");}
}

WebMvcConfigurer接口是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件来实现基本的配置需要。

InterceptorConfig内的addInterceptor需要一个实现HandlerInterceptor接口的拦截器实例,addPathPatterns方法用于设置拦截器的过滤路径规则。

addInterceptors方法中,我们将第6步定义的实现了HandlerInterceptor接口的拦截器实例authenticationInterceptor,添加至InterceptorRegistration中,并设置过滤路径。现在,我们所有请求都要经过authenticationInterceptor的拦截,拦截器authenticationInterceptor通过preHandle方法的业务过滤,判断是否有@TokenRequired 来决定是否需要登录。

8.定义接口方法并添加注解

`@RestController
@RequestMapping("user")
public class UserController {@AutowiredUserService userService;/*** 用户登录* @param user* @return*/@PostMapping("/login")public ResultDTO login( User user){String token = userService.login(user.getUsername(), user.getPassword());if (token == null) {return ResultDTO.failure(new ResultError(UserError.PASSWORD_OR_NAME_IS_ERROR));}Map<String, String> tokenMap = new HashMap<>();tokenMap.put("token", token);return ResultDTO.success(tokenMap);}@TokenRequired@GetMapping("/hello")public String getMessage(){return "你好哇,我是小码仔";}
}
不加注解的话默认不验证,登录接口一般是不验证的。所以我在getMessage()中加上了登录注解,说明该接口必须登录获取token后,在请求头中加上token并通过验证才可以访问。

请求验证

我在代码中对getMessage()添加了@TokenRequired注解,此刻访问该方法时必须要通过登录拿取到token值,并在请求头中添加token才可以访问。我们现在做以下校验:

  1. 直接访问,不在请求头里添加token:

如上图所示,请求结果显示:无token,请重新登录

2.访问登录接口,获取token,并在请求头中添加token信息:

此时,访问成功

3.15分钟后,token失效,我们再次在请求头中添加token信息访问:

此时token已失效,返回:无效的令牌。 

总结

回顾一下本次JWT使用的基本业务判断流程:

  1. 用户访问页面,前端请求相关接口,经过拦截器,拦截器中从 http 请求头中取出 token;
  2. 检查该接口有没有@TokenRequired注解,如果没有,直接放行;如果有,检验token是否为空;
  3. 如果token为空,访问失败;token不为空,则查询用户信息并校验token;
  4. 校验通过,则进行业务访问处理,校验失败则返回token失效信息。

不足之处:本次集成只是做一个简单的JWT使用介绍,没有实现token的过期刷新机制,此种情况下用户每隔15分钟就需要重新登录一次,如果在实际生产环境中使用,可能会被用户打死,因此实际开发中并不推荐。

关于token的刷新机制,将在下篇文章中为大家解读并附上源码。

本次集成代码地址:https://github.com/bailele1995/springboot-jjwt.git
来源:https://juejin.im/post/5ea27c5be51d4546c27bdf94?utm_source=tuicool&utm_medium=referral

springboot entity date_SpringBoot+JWT实战(附源码)相关推荐

  1. Django项目实战(附源码免费下载)

    制作图书管理系统(末尾附源码) 第一步先更改settings.py里面的必要配置,更改或附件项如下 INSTALLED_APPS = ['django.contrib.admin','django.c ...

  2. 实战篇:Security+JWT组合拳 | 附源码

    简介 先赘述一下身份认证和用户授权: 用户认证(Authentication):系统通过校验用户提供的用户名和密码来验证该用户是否为系统中的合法主体,即是否可以访问该系统: 用户授权(Authoriz ...

  3. 亲手撸了一个SpringBoot+Vue的企业级项目(附源码)

    点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 简介 SpringBoot和Vue,前后端分离,我们开源一套漂亮的代码和一套整洁的代码规范,让大家在这浮躁的代码世界里感受到一股把代码写好 ...

  4. ANDROID物联网开发从入门到实战附源码

    本书从获取源码和搭建应用开发环境开始讲起,依次讲解了基础知识篇.数据传输篇.信息识别篇.传感器应用篇和技术提高篇这 5大部分内容. 目录 第1篇 基础知识篇 第1章 Android系统介绍 2 1.1 ...

  5. 基于SpringBoot的健身房管理系统【附源码】

    基于SSM的校园点餐外卖配送系统(点餐系统.外卖系统.配送系统) 开发语言:Java 数据库:MySQL 技术:Spring+SpringMVC+MyBatis+ElementUI 工具:IDEA/E ...

  6. 基于SpringBoot的教务系统【附源码】

    基于SpringBoot的教务系统 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse.Navicat.Maven 角色分为管理员.教师.学生 管理员可 ...

  7. springboot实验室管理系统-计算机毕设 附源码86757

    springboot实验室管理系统 摘 要 验室管理系统是将实验室的分析仪器通过计算机网络连起来,采用科学的管理思想和先进的数据库技术,实现以实验室为核心的整体环境的全方位管理.它集用户管理,实验室信 ...

  8. 手把手搭建SpringBoot电子商城网站【附源码】(毕设)

    文末源码加视频教学

  9. 【首次分享】企业级车载系统开发指南+项目实战(附源码)

    前言 Android 现在已经拥有十分成熟的开发体系,成熟也说明了这个系统的带来的开发红利消退了,说通俗点就是可以跳槽岗位少了,随着最近几年小程序和公众号崛起,让app应用需求量断崖式下降.所以现在更 ...

最新文章

  1. 我们学校的DV作品——《感悟青春》
  2. 阿里mysql数据库同步_如何对MySQL数据库中的数据进行实时同步-阿里云开发者社区...
  3. web.py开发web 第四章 Sqlalchemy(事件监听与初始化)
  4. 蜗牛慢慢爬 LeetCode 6. ZigZag Conversion [Difficulty: Medium]
  5. qmake生成vs2013工程文件
  6. 算法与数据结构1800题 之 栈和队列
  7. php中几个数组函数array_slice() array_filter array_unique() in_array()
  8. B2B、B2C、C2C、O2O分别是什么意思?
  9. 【rmzt】动漫性感美女win7主题_8.13
  10. linux ms08 067漏洞,MS08067攻击实验失败的原因是什么?
  11. matlab 多子图_MATLAB|subplot子图分块绘制的方法
  12. 算法- C语言实现侏儒(地精)排序(Gnome_sort)
  13. 电脑开机遇到二维码怎么办?
  14. linux如何给脚本等创建一个桌面启动图标
  15. 线性代数——正交矩阵
  16. 用Java写给女朋友,用加密算法给女朋友写封情书
  17. 关于最近研究的绕过某校园网认证登录-DNS隧道-dns2tcp
  18. 读《玺印篆刻赏析》有感
  19. 《愤怒的小鸟》之父魏皮特:小鸟王国的品牌之路
  20. 网络视频直播系统开发,连麦视频分屏处理如何实现?

热门文章

  1. php static 访问,使用PHP访问Static方法的最佳方法
  2. 如何判断是不是真正的物理隔离网络光端机
  3. [渝粤教育] 重庆大学 电子商务 参考 资料
  4. 【渝粤教育】国家开放大学2018年秋季 0717-21T社会保障基础 参考试题
  5. [渝粤教育] 西南科技大学 电子技术基础 在线考试复习资料(1)
  6. [渝粤教育] 西南科技大学 机械专业外语 在线考试复习资料2021版
  7. 【渝粤题库】国家开放大学2021春2585城市轨道交通概论答案
  8. mysql 返回多行数据_mysql – 如何连接多个表,包括查找表和返回行中的数据
  9. java 收集系统资源_方法:Linux 下用JAVA获取CPU、内存、磁盘的系统资源信息
  10. Verilog基本语法初学