SpringBoot集成JWT

java1234

共 10023字,需浏览 21分钟

 ·

2020-12-28 03:29

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

  作者 |  Bruce.Chang.Lee

来源 |  urlify.cn/aeiQvq

66套java从入门到精通实战课程分享

1、什么是JWT?

关于JWT的详细介绍,请参考JSON Web Token 入门教程

2、Spring Boot集成JWT

2.1、pom.xml 文件中引入相关依赖包

  
    com.cnblogs.javalouvre
    spring-boot-tutorial
    1.0.0
  


  
    
      org.apache.commons
      commons-lang3
    


    
      org.springframework.boot
      spring-boot-starter-web
    

    
      io.jsonwebtoken
      jjwt
      0.9.1
    

  

2.2、aplication.yml 配置JWT相关参数

# token配置
token:
    # 令牌自定义标识
    header: Authorization
    # 令牌密钥(自定义)
    secret: 6F3931D35F0395DF82B032B8019AC57D
    # 令牌有效期(默认30分钟)
    expireTime: 30

2.3、TokenService.java 设置Token生成与解析

package com.cnblogs.javalouvre.service;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class TokenService {

    /**
     * 生成Token
     *
     * @param sub
     * @return
     */
    public String createToken(String sub) {
        Calendar calendar = GregorianCalendar.getInstance();
        Date iat = calendar.getTime();
        calendar.add(GregorianCalendar.MINUTE, amount);
        Date exp = calendar.getTime();

        return Jwts.builder()//
                .setHeaderParam("typ""JWT")// 令牌类型
                .setSubject(sub)// 主题
                .setIssuedAt(iat) // 签发时间
                .setExpiration(exp)// 过期时间
                .signWith(SignatureAlgorithm.HS512, secretKey)// 签名算法、秘钥
                .compact();
    }

    /**
     * 获取Token中注册信息
     *
     * @param token
     * @return
     */
    public Claims getBody(String token) {
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
    }

    /**
     * 获取签发日期
     *
     * @param token
     * @return
     */
    public Date getIssuedAt(String token) {
        return getBody(token).getIssuedAt();
    }

    /**
     * 获取过期时间
     *
     * @param token
     * @return
     */
    public Date getExpiration(String token) {
        return getBody(token).getExpiration();
    }

    /**
     * 获取主题信息
     *
     * @param token
     * @return
     */
    public String getSubject(String token) {
        return getBody(token).getSubject();
    }

    // 令牌秘钥
    @Value("${token.secret}")
    private String secretKey;

    // 令牌有效期(默认30分钟)
    @Value("${token.expireTime}")
    private int    amount;
}

2.4、TokenHandlerInterceptor.java 定义拦截器

package com.cnblogs.javalouvre.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.cnblogs.javalouvre.service.TokenService;

import io.jsonwebtoken.SignatureException;

@Component
public class TokenHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String uri = request.getRequestURI();
        if (uri.contains("/login")) {
            return true;
        }

        String token = request.getHeader(header);
        if (StringUtils.isBlank(token)) {
            throw new SignatureException(StringUtils.EMPTY);
        }

        tokenService.getBody(token);

        return true;
    }

    @Autowired
    private TokenService tokenService;

    // 令牌自定义标识
    @Value("${token.header}")
    private String       header;
}

2.5、ResourceConfig.java 配置拦截器

package com.cnblogs.javalouvre.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.cnblogs.javalouvre.interceptor.TokenHandlerInterceptor;

@Configuration
public class ResourceConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenHandlerInterceptor).addPathPatterns("/**");
    }

    @Autowired
    private TokenHandlerInterceptor tokenHandlerInterceptor;
}

2.6、IndexController.java 登录入口

package com.cnblogs.javalouvre.web;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

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.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import com.cnblogs.javalouvre.dto.AjaxResult;
import com.cnblogs.javalouvre.service.TokenService;

@RestController
public class IndexController {

    @PostMapping(path = "/login", produces = APPLICATION_JSON_VALUE)
    public AjaxResult login(String username, String password) {
        // 模拟数据库操作
        if ("admin".equals(username) && "admin123".equals(password)) {
            return AjaxResult.success("操作成功", tokenService.createToken(username));
        }

        return AjaxResult.error("账号或密码错误");
    }

    @GetMapping(path = "/index", produces = APPLICATION_JSON_VALUE)
    public AjaxResult execute(@RequestHeader("Authorization") String token) {
        return AjaxResult.success(tokenService.getSubject(token));
    }

    @Autowired
    private TokenService tokenService;
}

2.7、其他辅助类

2.7.1、GlobalExceptionHandler.java 全局异常处理
package com.cnblogs.javalouvre.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.cnblogs.javalouvre.dto.AjaxResult;

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(SignatureException.class)
    @ResponseBody
    public AjaxResult signatureException() {
        return AjaxResult.error("Token为空");
    }

    @ResponseBody
    @ExceptionHandler(ExpiredJwtException.class)
    public AjaxResult expiredJwtException() {
        return AjaxResult.error("Token过期");
    }

    @ResponseBody
    @ExceptionHandler(MalformedJwtException.class)
    public AjaxResult malformedJwtException() {
        return AjaxResult.error("Token数据错误");
    }
}
2.7.2、HttpStatus.java 返回消息状态定义
package com.cnblogs.javalouvre.constants;

public final class HttpStatus {

    public static final int OK                    = 200;

    public static final int INTERNAL_SERVER_ERROR = 500;

    private HttpStatus() {
     // DO NOTHING
    }

}
2.7.3、AjaxResult.java 返回消息定义
package com.cnblogs.javalouvre.dto;

import java.util.HashMap;
import java.util.Objects;

import com.cnblogs.javalouvre.constants.HttpStatus;

public class AjaxResult extends HashMap {

    private static final long   serialVersionUID = 242180064461040653L;

    // 状态码
    private static final String CODE_TAG         = "code";

    // 返回内容
    private static final String MSG_TAG          = "msg";

    // 数据对象
    private static final String DATA_TAG         = "data";

    public AjaxResult() {
        // DO NOTHING
    }

    public AjaxResult(int code, String msg) {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }

    public AjaxResult(int code, String msg, Object data) {
        this(code, msg);

        if (Objects.nonNull(data)) {
            super.put(DATA_TAG, data);
        }
    }

    public static AjaxResult success() {
        return AjaxResult.success("操作成功");
    }

    public static AjaxResult success(Object object) {
        return AjaxResult.success("操作成功", object);
    }

    public static AjaxResult success(String msg) {
        return AjaxResult.success(msg, null);
    }

    public static AjaxResult success(String msg, Object data) {
        return new AjaxResult(HttpStatus.OK, msg, data);
    }

    public static AjaxResult error() {
        return AjaxResult.success("操作失败");
    }

    public static AjaxResult error(Object object) {
        return AjaxResult.error("操作失败", object);
    }

    public static AjaxResult error(String msg) {
        return AjaxResult.error(msg, null);
    }

    public static AjaxResult error(String msg, Object data) {
        return new AjaxResult(HttpStatus.INTERNAL_SERVER_ERROR, msg, data);
    }
}

2.8、App.java 入口类

package com.cnblogs.javalouvre;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

3、目录结构

│  pom.xml
│      
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─cnblogs
    │  │          └─javalouvre
    │  │              │  App.java
    │  │              │  
    │  │              ├─config
    │  │              │      ResourceConfig.java
    │  │              │      
    │  │              ├─constants
    │  │              │      HttpStatus.java
    │  │              │      
    │  │              ├─dto
    │  │              │      AjaxResult.java
    │  │              │      
    │  │              ├─exception
    │  │              │      GlobalExceptionHandler.java
    │  │              │      
    │  │              ├─interceptor
    │  │              │      TokenHandlerInterceptor.java
    │  │              │      
    │  │              ├─service
    │  │              │      TokenService.java
    │  │              │      
    │  │              └─web
    │  │                      IndexController.java
    │  │                      
    │  └─resources
    │          application.yml
    │          
    └─test
        ├─java
        └─resources





粉丝福利:Java从入门到入土学习路线图

???

?长按上方微信二维码 2 秒


感谢点赞支持下哈 

浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报