1). 首先我们先来实现JWT令牌的生成。要想使用JWT令牌,需要先引入JWT的依赖:
- <!-- JWT依赖-->
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
复制代码 在引入完JWT来赖后,就可以调用工具包中提供的API来完成JWT令牌的生成和校验。工具类:Jwts
2). 生成JWT代码实现:
- @Test
- public void testGenJwt() {
- Map<String, Object> claims = new HashMap<>();
- claims.put("id", 10);
- claims.put("username", "itheima");
- String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "aXRjYXN0")
- .addClaims(claims)
- .setExpiration(new Date(System.currentTimeMillis() + 12 * 3600 * 1000))
- .compact();
- System.out.println(jwt);
- }
复制代码
运行测试方法:
- eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMwfQ.fHi0Ub8npbyt71UqLXDdLyipptLgxBUg_mSuGJtXtBk
复制代码
3). 实现了JWT令牌的生成,下面我们接着使用Java代码来校验JWT令牌(解析生成的令牌):
- @Test
- public void testParseJwt() {
- Claims claims = Jwts.parser().setSigningKey("aXRjYXN0")
- .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MTAsInVzZXJuYW1lIjoiaXRoZWltYSIsImV4cCI6MTcwMTkwOTAxNX0.N-MD6DmoeIIY5lB5z73UFLN9u7veppx1K5_N_jS9Yko")
- .getBody();
- System.out.println(claims);
- }
复制代码 运行测试方法:
- {id=10, username=itheima, exp=1701909015}
复制代码
令牌解析后,我们可以看到id和过期时间,如果在解析的过程当中没有报错,就说明解析成功了。
完整生成JWT令牌和解析案例:
- @Test
- public void genJwt(){
- Map<String, Object> claims = new HashMap<>();
- claims.put("id", 10);
- claims.put("username", "itheima");
- String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "aXRjYXN0")
- .addClaims(claims)
- .setExpiration(new Date(System.currentTimeMillis() + 60 * 1000)) //有效期60s
- .compact();
- System.out.println(jwt);
- //输出结果:eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjczMDA5NzU0fQ.RcVIR65AkGiax-ID6FjW60eLFH3tPTKdoK7UtE4A1ro
- }
- @Test
- public void parseJwt(){
- Claims claims = Jwts.parser()
- .setSigningKey("aXRjYXN0")//指定签名密钥
- .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjczMDA5NzU0fQ.RcVIR65AkGiax-ID6FjW60eLFH3tPTKdoK7UtE4A1ro")
- .getBody();
- System.out.println(claims);
- }
复制代码
实践开发项目:
1,登录成功后创建JWT令牌
- @PostMapping("/login")
- @ApiOperation(value = "员工登录接口")
- public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
- log.info("员工登录:{}", employeeLoginDTO);
- Employee employee = employeeService.login(employeeLoginDTO);
- //登录成功后,生成jwt令牌
- Map<String, Object> claims = new HashMap<>();
- claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
- // claims.put("id", employee.getId());
- // claims.put("username", employee.getUsername());
- String token = JwtUtil.createJWT(
- jwtProperties.getAdminSecretKey(),
- jwtProperties.getAdminTtl(),
- claims);
- EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
- .id(employee.getId())
- .userName(employee.getUsername())
- .name(employee.getName())
- .token(token)
- .build();
- return Result.success(employeeLoginVO);
- }
复制代码
2,JWT令牌拦截器拦截令牌,并解析内容
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- // 获取当前线程ID
- long threadId = Thread.currentThread().getId();
- System.out.println("线程ID:" + threadId);
- //判断当前拦截到的是Controller的方法还是其他资源
- if (!(handler instanceof HandlerMethod)) {
- //当前拦截到的不是动态方法,直接放行
- return true;
- }
- //1、从请求头中获取令牌
- String token = request.getHeader(jwtProperties.getAdminTokenName());
- //2. 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
- if(!StringUtils.hasLength(token)){ //jwt为空
- log.info("获取到jwt令牌为空, 返回错误结果");
- response.setStatus(HttpStatus.SC_UNAUTHORIZED);
- return false;
- }
- //3、校验令牌
- // 校验过程:
- // 使用 JwtUtil.parseJWT 方法解析 JWT 令牌
- // 传入两个参数:
- // jwtProperties.getAdminSecretKey():获取管理员密钥,用于验证签名
- // token:客户端传递的 JWT 令牌
- // 如果 token 有效且签名正确,会返回 Claims 对象
- // 如果 token 无效、过期或签名不正确,则会抛出异常
- try {
- log.info("jwt校验:{}", token);
- Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
- Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
- log.info("当前员工id:", empId);
- // 将当前登录用户的ID保存到当前线程的LocalThread中
- BaseContext.setCurrentId(empId);
- //3、通过,放行
- return true;
- } catch (Exception ex) {
- //4、不通过,响应401状态码
- response.setStatus(401);
- return false;
- }
- }
复制代码
完整代码:
sky-take-out.zip
(72.67 KB, 下载次数: 0, 价格: 10 金钱)
如何获得当前登录用户ID,如何传值到service,线程局部变量ThreadLocal解决
https://www.zidiu.com/thread-44-1-1.html
|
|