SpringSecurity集成JWT实现后端认证授权保姆级教程-工具类准备篇

Java
200
0
0
2024-03-23
标签   Spring
🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法

🎈创建常用常量和Result返回类

在这里插入图片描述

OtherConstants.java

package com.example.demo.common.constants;

/**
 * @author: zsqt
 * Package:  com.zsqt.security.constants
 * @date: 2024/1/3 16:52
 * @Description:
 * @version: 1.0
 */
public class OtherConstants {

    public static final String AUTH_TOKEN = "Authorization"; //TOKEN对应的KEY

    public static final Integer TOKEN_SITE = 7; //TOKEN前边的Bearer 字符串 共有7个字符

    public static final String USER_PREFIX = "USER:"; //用户前缀
}

Result.java

package com.example.demo.common.Vo;
import lombok.Data;
@Data
public class Result<T> {
    private Integer code;
    private String msg;
    private T data;
    public Result() {
    }
    public Result(T data) {
        this.data = data;
    }
    /**
     * 成功返回结果
     * @return
     */
    public static Result success() {
        Result result = new Result<>();
        result.setCode(200);
        result.setMsg("成功");
        return result;
    }
    /**
     * 成功返回结果
     * @param data
     * @return
     * @param <T>
     */
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>(data);
        result.setCode(200);
        result.setMsg("成功");
        return result;
    }
    /**
     * 失败返回结果
     * @param code
     * @param msg
     * @return
     */
    public static Result error(Integer code, String msg) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
    /**
     * 失败返回结果
     * @param msg
     * @return
     */
    public static Result error500(String msg) {
        Result result = new Result();
        result.setCode(500);
        result.setMsg(msg);
        return result;
    }
}

🎈跨域配置类

在这里插入图片描述

CorsConfig.class

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOriginPatterns("*")
                // 是否允许cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
    }
}

🎈Swagger配置类

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author: zsqt
 * Package:  com.zsqt.security.config
 * @date: 2024/1/4 14:29
 * @Description:
 * @version: 1.0
 */
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
    @Bean
    public Docket createDocApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .groupName("接口文档")
                .pathMapping("/")
                .apiInfo(DocApi());
    }
    /**
     * 构建 api文档的详细信息函数,注意这里的注解引用的是哪个
     */
    private ApiInfo DocApi() {
        return new ApiInfoBuilder()
                //页面标题
                .title("接口测试工具")
                //创建人
                .contact(new Contact("", "", ""))
                //版本号
                .version("1.0")
                //描述
                .description("接口测试工具")
                .build();
    }
}

🎈JwtUtil配置类

在这里插入图片描述

JwtUtil.java

package com.example.demo.utils;
/**
 * @author: zsqt
 * Package:  com.zsqt.security.utils
 * @date: 2024/1/3 16:52
 * @Description:
 * @version: 1.0
 */
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.demo.domain.CustUser;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.*;
import static com.example.demo.common.constants.OtherConstants.*;
@Component
@RequiredArgsConstructor
public class JwtUtil {
    private static final String key = "ims_test"; // 密钥
    private final RedisTemplate redisTemplate; //

    /**
     * 创建jwt
     *
     * @param details 用户登陆信息
     * @return String
     */
    public String createJwt(CustUser details) {
        Algorithm algorithm = Algorithm.HMAC256(key);
        return JWT.create()
                .withJWTId(UUID.randomUUID().toString())
                .withClaim("user",details.getId()) //把用户id存入token中
                .withExpiresAt(expireTime())
                .withIssuedAt(new Date())// 签发时间
                .sign(algorithm);
    }

    /**
     * 解析token
     * @param authToken token
     * @return DecodedJWT
     */
    public DecodedJWT resolveJwt(String authToken) {
        String token = convertToken(authToken);
        if (token == null)
            return null;
        Algorithm algorithm = Algorithm.HMAC256(key);
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token); // 验证token
            Date expiresAt = verify.getExpiresAt(); // token过期时间
            return new Date().after(expiresAt) ? null : verify; // 判断是否过期
        } catch (JWTVerificationException jwtVerificationException) {
            return null;
        }
    }

    /**
     * 检查用户在redis中是否存在
     * @param user
     * @return
     */
    public boolean checkRedis(CustUser user) {
        if(redisTemplate.opsForValue().get(USER_PREFIX + user.getId()) == null){
            return false;
        }else{
            return true;
        }
    }

    /**
     * 根据解析后的token获取用户信息
     *
     */
    public CustUser toUser(DecodedJWT jwt) {
        Integer uid;
        try {
            Map<String, Claim> claims = jwt.getClaims();
            uid = claims.get("user").asInt();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }
        CustUser user = (CustUser) redisTemplate.opsForValue().get(USER_PREFIX +uid);
        if(Objects.isNull(user)){
            throw new RuntimeException("用户未登录");
        }
        return user;
    }

    /**
     * 在请求头信息中获取token 去掉对应的前缀
     */
    private String convertToken(String authToken) {
        if (!StringUtils.hasText(authToken) || !authToken.startsWith("Bearer "))
            return null;
        return authToken.substring(TOKEN_SITE);// 截取token 因为token前面有Bearer空格
    }

    /**
     * 设置token过期时间
     * @return
     */
    private Date expireTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 30);
        return calendar.getTime();
    }
}

测试一下swagger文档 http://localhost:8080/doc.html#/home

在这里插入图片描述

到这工具类准备就绪,接下来就要进行各种security认证配置了。

🍚总结

大功告成,撒花致谢🎆🎇🌟,关注我不迷路,带你起飞带你富。