【Spring Boot整合 JWT】

2 篇文章 0 订阅
1 篇文章 0 订阅

简介

使用OAuth2协议实现统一认证会非常烦锁,而且会影响到性能。
直接利用一个Token数据实现分布式认证信息的存储,简单且难度低,token数据量小网络传输更快

一、 配置JWT相关信息

1、引入依赖

		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

2、配置jwt相关属性

server:
  port: 8083
spring:
  application:
    name: carbon #应用名称
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/carbon1?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
mybatis:
  type-aliases-package: com.dz.carbon.pojo
  mapper-locations: classpath:mapper/*Mapper.xml
carbon: #自定义配置
  config: #自定义配置项
    jwt:
      sign: carbon #JWT 证书相关签名
      issuer: ranzong # 证书签发人
      secret: ranzongCarBon #密钥
      expire: 100 #有效时长

3、创建JWT属性配置类,接收application中属性内容

@ConfigurationProperties(prefix = "carbon.config.jwt")
@Component
@Data
public class JWTConfigProperies {
    private String sign;    // 证书签名信息
    private String issuer; // 签名信息
    private String secret; // 加密密钥
    private long expire; // 失效时间(单位:s)
}

二、编写JWTUtils类

1、注入jwt属性配置类,定义应用名,采用HS256算法
在这里插入图片描述

2、设置加密密钥信息(考虑安全性,额外通过base64加密)

	public static SecretKey generalKey(){
        byte[] encodedKey = Base64.decodeBase64(Base64.encodeBase64(jwtConfigProperies.getSecret().getBytes()));
        return new SecretKeySpec(encodedKey,0,encodedKey.length,"AES");
    }

3、创建生成token的方法

	public static String createToken(Map<String, Object> map){
        // 创建jwt
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND, jwtConfigProperies.getExpire());

            Map<String,Object> headers = new HashMap<String,Object>();
            headers.put("author","代总");
            headers.put("module",applicationName);

            return Jwts.builder()
                    .setSubject(new ObjectMapper().writeValueAsString(map)) // 用户信息
                    .setIssuedAt(new Date()) //签发时间
                    .setExpiration(calendar.getTime()) //过期时间
                    .setHeader(headers) //头部信息
                    .setId("carbon"+ UUID.randomUUID()) //唯一标识
                    .signWith(signatureAlgorithm,generalKey())
                    .compact(); // 创建token
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

4、创建验证token合法性方法

public static boolean verify(String token){
        try{
            Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
            return true;
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

5、创建获取token信息方法

public static Jws<Claims> getTokenInfo(String token){
        if (StringUtils.isNullOrEmpty(token)) return null;
        return Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token);
    }

6、创建刷新token的方法

	public String refresh(String token){
        // 验证token
        if (!verify(token)) return null;

        ObjectMapper mapper = new ObjectMapper();
        try {
            Map<String,Object> map = mapper.readValue(Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody().getSubject(), HashMap.class);
            return createToken(map);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

7、创建验证token并返回结果

	// 验证token获取状态
    public static Result checkToken(String token){
        try{
            Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
        }
        catch (ExpiredJwtException e){
            return new Result(false,StatusCode.ERROR.getCode(), "token过期!");
        }
        catch (Exception e){
            return new Result(false,StatusCode.ERROR.getCode(), "token无效!");
        }
        return new Result(true,StatusCode.SUCCESS.getCode(), "token有效");
    }

8、编写测试类,测试Jwt业务方法

@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@SpringBootTest(classes = CarbonApplication.class)

public class TestToken {
    @Autowired
    private UserService userService;

    @Test
    public void testCreateToken (){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("user",userService.queryById(1));
        System.out.println(JWTUtils.createToken(map));
    }

    @Test
    public void testgetToken () throws JsonProcessingException {
        Jws<Claims> tokenInfo = JWTUtils.getTokenInfo("eyJhdXRob3IiOiLku6PmgLsiLCJtb2R1bGUiOiJjYXJib24iLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VyXCI6e1widWlkXCI6MSxcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwiZW1haWxcIjpcIjEyMzQ1NkBxcS5jb21cIixcInBhc3N3b3JkXCI6XCIxMjM0NTZcIixcImF2YXRhclwiOlwiXCJ9fSIsImlhdCI6MTY5ODIxOTM1MSwiZXhwIjoxNjk4MjE5NDUxLCJqdGkiOiJjYXJib25jZmUxZTM2ZC04YThlLTQ4YjYtYWJiMS0xYzhjZTE3OTYzZWUifQ.T_tK9nMdBoZbvgnZKdk6VVyoQOpYS3ST28cmhooG91g");
        System.out.println(tokenInfo.getHeader());
        System.out.println(tokenInfo.getSignature());
        System.out.println(tokenInfo.getBody());
        ObjectMapper mapper = new ObjectMapper();
        Map map =  mapper.readValue(tokenInfo.getBody().getSubject(), HashMap.class);
        System.out.println(map.get("user"));
    }

    @Test
    public void testVerify(){
        System.out.println(JWTUtils.verify("eyJhdXRob3IiOiLku6PmgLsiLCJtb2R1bGUiOiJjYXJib24iLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VyXCI6e1widWlkXCI6MSxcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwiZW1haWxcIjpcIjEyMzQ1NkBxcS5jb21cIixcInBhc3N3b3JkXCI6XCIxMjM0NTZcIixcImF2YXRhclwiOlwiXCJ9fSIsImlhdCI6MTY5ODIxODY0NywiZXhwIjoxNjk4MjE4NzQ3LCJqdGkiOiJjYXJib24yYjQ3NTE2Mi0xYjAzLTQ3NGYtYTZlYS1lMGM3MTUzMTkxNDkifQ.XSCrlcB6fRqfnhd7-rUbKG5-F_PZplX76R5D5YTpoMo"));
    }

    @Test
    public void testRefresh(){
        System.out.println(JWTUtils.refresh("eyJhdXRob3IiOiLku6PmgLsiLCJtb2R1bGUiOiJjYXJib24iLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJ1c2VyXCI6e1widWlkXCI6MSxcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwiZW1haWxcIjpcIjEyMzQ1NkBxcS5jb21cIixcInBhc3N3b3JkXCI6XCIxMjM0NTZcIixcImF2YXRhclwiOlwiXCJ9fSIsImlhdCI6MTY5ODIxOTA0NSwiZXhwIjoxNjk4MjE5MTQ1LCJqdGkiOiJjYXJib24yYTU4NjAwYS0wYjM0LTQyOTYtODg4OS02MWM4ZjU5ZDkyNjAifQ.isOUg0sQl3mq5VQae0Pk7eEjs9GrCRiruNr1HIoVsf0"));
    }

三、Token拦截

1、创建拦截器类

public class JWTInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Result result = JWTUtils.checkToken(request.getHeader("X-Token"));
        if (!result.getFlag()) return true;
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(new ObjectMapper().writeValueAsString(result));
        return false;
    }
}

2、添加拦截器配置类

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值