JWT认证实现

1,jwt认证流程图

JWT认证实现_第1张图片

2,token组成

Header+Playload+Signature

头部(Header),格式如下:

{ 
“typ”: “JWT”, 
“alg”: “HS256” 
} 

头部存储认证类型和加密算法,将此json使用Base64编码可得到如下个格式的字符串:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

有效载荷(Playload):

{
	"role": [],
	"iss": "baidu",
	"exp": 1638841050,
	"userName": "管理员",
	"department": [],
	"iat": 1638840690,
	"userId": "1",
	"account": "admin"
}

有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。有效载荷也使用Base64编码得到如下格式的字符串:

eyJyb2xlIjpbXSwiaXNzI

签名(Signature):

将Header和Playload拼接生成一个字符串str=“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjpbXSwiaXNzI”,
使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT,
即我们需要的令牌(token),形如:str.”签名字符串”。

3,代码实现

生成token


	public static final long TOKEN_EXPIRE_TIME = 6 * 60 * 1000;

/**
     * 生成token
     *
     * @param userId     用户ID
     * @param account    登录名
     * @param userName   用户名称
     * @param role       角色ID集合
     * @param department 部门ID集合
     * @param jwtSecret  生成jwt的秘钥,由网关传入
     * @return token
     */
    public static String generateToken(Long userId, String account, String userName, List<Long> role, List<Long> department, String jwtSecret) {
        Date now = new Date();
        // 加密算法
        Algorithm algorithm = Algorithm.HMAC256(jwtSecret);

        return JWT.create()
                //签发人
                .withIssuer(ISSUER)
                //签发时间
                .withIssuedAt(now)
//                .withSubject()
                //过期时间
                .withExpiresAt(new Date(now.getTime() + TOKEN_EXPIRE_TIME))
                .withClaim("userId", userId)
                .withClaim("userName", userName)
                .withClaim("account", account)
                .withClaim("role", role)
                .withClaim("department", department)
                .sign(algorithm);
    }


  /**
     * 获取用户名称
     *
     * @param token toke
     * @return 用户姓名
     */
    public static String getUserName(String token) {
        try {
            return JWT.decode(token).getClaim("userName").asString();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }

    /**
     * 获取用户角色
     *
     * @param token token
     * @return 角色ID集合
     */
    public static List<Long> getRole(String token) {
        try {
            return JWT.decode(token).getClaim("role").asList(Long.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

验证token

3.1 网关验证token

 /**
     * 签发人
     */
    private static final String ISSUER = "baidu";

    /**
     * 验证token是否合法
     *
     * @param token
     * @return
     * JwtSecret为密钥,随机生成
     */
    public static boolean verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256("JwtSecret");
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.error("验证token失败 {}", e.getMessage());
        }
        return false;
    }

3.2 使用拦截器验证token


/**
 * 拦截器
 */
@Component
@Slf4j
public class JwtHandler implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws IOException {
        Map<String,Object> map=new HashMap<>();
        String token = Request.getHeaderParam(request, "token");
        try {
            Algorithm algorithm = Algorithm.HMAC256("JwtSecret");
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("baidu")
                    .build();
            verifier.verify(token);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            map.put("status",false);
            map.put("msg","认证失败");
        }
        //jackson 将map转换为json
        String json=new ObjectMapper().writeValueAsString(map);
        response.getWriter().println(json);
        return false;
    }

拦截器注册


@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    /**
     * 注册拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new UserHandlerAdapter())
                .addPathPatterns("/user/verify")     //拦截请求路径
                .excludePathPatterns("/user/login"); //不拦截请求路径
    }

}

4,更多优秀文章

https://blog.csdn.net/wd521521/article/details/82856203

https://blog.csdn.net/zunguitiancheng/article/details/90417574

https://blog.csdn.net/houmenghu/article/details/99181326

https://zhuanlan.zhihu.com/p/91420328

你可能感兴趣的:(Java,java,后端)