Springboot集成JWT做登录拦截

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lxj673011332/article/details/81808908
为什么需要JWT

在传统的 session 验证中,服务端必须保存 session ID,用于与用户传过来的 cookie 验证。而在一开始保存 session ID 时, 只会保存在一台服务器上,所以只能由一个 server 应答,就算其他服务器有空闲也无法应答,因此也利用不到分布式服务器的优点。
而 JWT 依赖的是在客户端本地保存验证信息,不需要利用服务器保存的信息来验证,所以任意一台服务器都可以应答,服务器的资源也被较好地利用。

JWT介绍
JWT官网

spring集成JWT
  • 添加JWT依赖
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
  • 添加JWT配置
audience:
  clientId: 098f6bcd4621d373cade4e832627b4f6
  base64Secret: MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=
  name: restapiuser
  expiresSecond: 172800
  • 配置JWT实体类
@Component
@ConfigurationProperties(prefix = "audience")
public class Audience {


    private String clientId;
    private String base64Secret;
    private String name;
    private int expiresSecond;


    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getBase64Secret() {
        return base64Secret;
    }

    public void setBase64Secret(String base64Secret) {
        this.base64Secret = base64Secret;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getExpiresSecond() {
        return expiresSecond;
    }

    public void setExpiresSecond(int expiresSecond) {
        this.expiresSecond = expiresSecond;
    }
}
  • 使用拦截器配置JWT
@Component
public class JWTInterceptor implements HandlerInterceptor {


    @Autowired
    private Audience audience;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        final String authHeader = request.getHeader("authorization");
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        } else {
            if (null == authHeader || !authHeader.startsWith("bearer;")) {
                    throw new ServiceRuntimeException(new ErrorDetails(1004));

            }
        }
        final String token = authHeader.substring(7);
        try {
            final Claims claims = JwtHelper.parseJWT(token, audience.getBase64Secret());
            if (claims == null) {
                throw new ServiceRuntimeException(new ErrorDetails(1004));
            }
            request.setAttribute("CLAIMS", claims);
            return true;
        } catch (final Exception e) {
                throw new ServiceRuntimeException(new ErrorDetails(1004));
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)  {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e)  {

    }
}
  • 配置拦截器
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Bean
    JWTInterceptor jwtInterceptor(){
        return new JWTInterceptor();
    }
    //spring拦截器加载在springcontentText之前,所以这里用@Bean提前加载。否则会导致过滤器中的@AutoWired注入为空


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor()).addPathPatterns("/manage/**")
                .excludePathPatterns(Arrays.asList("/", "/login"));
    }

}
  • 登录返回token
        String jwtToken = JwtHelper.createJWT(admin.getAdminUsername(), admin.getAdminId(), audience.getClientId(),
                audience.getName(), audience.getExpiresSecond()*1000, audience.getBase64Secret());
        jwtToken = "bearer;" + jwtToken;
  • jwt工具类
public class JwtHelper {

    /**
     * 解析jwt
     */

    public static Claims parseJWT(String jsonWebToken, String base64Security){
        try{
            Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
                    .parseClaimsJws(jsonWebToken).getBody();
            return claims;
        }catch (Exception e){
            return null;
        }
    }

    /**
     *
     * @param name
     * @param userId
     * @param audience
     * @param issuer
     * @param TTLMillis
     * @param base64Security
     * @return
     */
    public static String createJWT(String name, Integer userId,
                                   String audience, String issuer, long TTLMillis, String base64Security){
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .claim("unique_name", name)
                .claim("userid", userId)
                .setIssuer(issuer)
                .setAudience(audience)
                .signWith(signatureAlgorithm, signingKey);
        //添加Token过期时间
        if (TTLMillis >= 0) {
            long expMillis = nowMillis + TTLMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp).setNotBefore(now);
        }

        //生成JWT
        return builder.compact();
    }
}

JWT配置教程

猜你喜欢

转载自blog.csdn.net/lxj673011332/article/details/81808908