SpringBoot整合JWT实现登录认证


1、JWT的构成

- 头部(header):描述该JWT的最基本的信息,如类型以及签名所用的算法。

- 负载(payload):存放有效信息的地方。

- 签证(signature):base64加密后的header、base64加密后的payload和密钥secret加密后组成。

2、整合JWT

2.1 引入JWT依赖

com.auth0

java-jwt

3.18.3

2.2 编写JWTUtils工具类

package com.stock.utils;

import com.auth0.jwt.JWT;

import com.auth0.jwt.JWTCreator;

import com.auth0.jwt.JWTVerifier;

import com.auth0.jwt.algorithms.Algorithm;

import com.auth0.jwt.interfaces.DecodedJWT;

import com.auth0.jwt.interfaces.Verification;

import java.util.Calendar;

import java.util.Map;

public class JWTUtils {

private static final String SING="@#$%^&*";

// 生成token

public static String getToken(Map map){

Calendar instance = Calendar.getInstance();

instance.add(Calendar.MINUTE,30);

//创建jwt builder

JWTCreator.Builder builder = JWT.create();

//payload

builder.withExpiresAt(instance.getTime());

map.forEach((k,v)->{

builder.withClaim(k,v);

});

//设置签名

String token = builder.sign(Algorithm.HMAC256(SING));

return token;

}

//验证令牌

public static void verifyToken(String token){

JWTVerifier require = JWT.require(Algorithm.HMAC256(SING)).build();

require.verify(token);

}

//获取token信息

public static DecodedJWT getTokenInfo(String token){

DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);

return verify;

}

}

2.3 编写拦截器

public class JWTInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {

System.out.println("OPTIONS请求,放行");

return true;

}

HashMap map = new HashMap<>();

String token = request.getHeader("token");

try {

JWTUtils.verifyToken(token);

return true;

}catch (SignatureVerificationException e){

map.put("msg","无效签名!");

}catch (TokenExpiredException e){

map.put("msg","token过期!");

}catch (AlgorithmMismatchException e){

map.put("msg","token加密算法不一致");

}catch (Exception e){

map.put("msg","无效签名!");

}

map.put("state",404);

map.put("path","/login");

//将map转化为字符串返回给前端

String result = new ObjectMapper().writeValueAsString(map);

response.setContentType("application/json;charset=UTF-8");

response.getWriter().println(result);

return false;

}

}


注意:

1、token存放在请求的header中;

2、在前后端分离的项目中,发送的GET/POST请求实则为两次请求。第一次请求为OPTIONS请求,第二次请求才是GET/POST请求;在OPTIONS请求中,不会携带请求头的参数,会导致在拦截器上获取请求头为空,自定义的拦截器拦截成功。第一次请求不能通过,就不能获取第二次的请求。所以需要在拦截器中加上如下代码来判断是否为OPTIONS请求,对于OPTIONS请求直接放过。

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {

System.out.println("OPTIONS请求,放行");

return true;

}

2.4 配置拦截器

package com.stock.config;

import com.stock.Interceptors.JWTInterceptor;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration

public class IntercepterConfg implements WebMvcConfigurer {

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new JWTInterceptor())

.addPathPatterns("/**")

.excludePathPatterns("/login");

}

}

2.5 编写Controller

package com.stock.controller;

import com.stock.entity.User;

import com.stock.result.Result;

import com.stock.service.UserService;

import com.stock.utils.JWTUtils;

import com.stock.utils.ResultUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController

public class LoginController {

private UserService userService;

@Autowired

public LoginController(UserService userService) {

this.userService = userService;

}

@PostMapping("/login")

public Result register(User user){

HashMap map = new HashMap<>();

map.put("username",user.getUserName());

String token = JWTUtils.getToken(map);

HashMap data = new HashMap<>();

data.put("token",token);

return ResultUtils.getresult(200,"登录成功!",data);

}

@GetMapping("/main")

public Result tomain(){

return ResultUtils.getresult(200,"访问成功",null);

}

}


2.6使用Postman测试

- 未登录前访问127.0.0.1:8888/main

- 先登录再访问127.0.0.1:8888/main

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章