1. 什么是JWT

JWT(JSON Web Token)是一种用于认证和授权的开放标准(RFC 7519)。它使用JSON对象作为令牌的安全传输机制,可用于验证身份信息和授予访问权限。JWT由三个部分组成:头部、载荷和签名。头部包含令牌的加密算法和类型信息;载荷中包含相关的用户信息和权限等;签名是利用密钥对头部和载荷进行加密算法生成的一串字符串。

2. Spring Boot中使用JWT

在Spring Boot中使用JWT进行身份和权限验证,通常需要实现自定义的认证过滤器和授权拦截器。

首先,创建一个自定义的JWT工具类,用于生成和解析JWT。


public class JwtUtils {
    private static final String SECRET_KEY = "your-secret-key"; // 用于签名的密钥
    private static final long EXPIRATION_TIME = 86400000; // 令牌的有效期(单位:毫秒)

    // 生成JWT
    public static String generateToken(String username, List roles) {
        Date now = new Date();
        Date expirationTime = new Date(now.getTime() + EXPIRATION_TIME);
        String token = Jwts.builder()
                .setSubject(username)
                .claim("roles", roles)
                .setIssuedAt(now)
                .setExpiration(expirationTime)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
        return token;
    }

    // 解析JWT
    public static Claims parseToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
        return claims;
    }
}

3. 实现认证过滤器

在Spring Boot中使用JWT进行身份验证的第一步是实现自定义的认证过滤器,该过滤器会在每个请求到达控制器之前进行身份验证。

可以通过继承OncePerRequestFilter抽象类实现自定义的认证过滤器,并在doFilterInternal方法中进行JWT的验证。


public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取请求头中的Authorization字段
        String authorizationHeader = request.getHeader("Authorization");
        if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            try {
                String jwtToken = authorizationHeader.substring(7);
                Claims claims = JwtUtils.parseToken(jwtToken);
                // 将认证信息存储到SecurityContextHolder中
                SecurityContextHolder.getContext().setAuthentication(new JwtAuthenticationToken(claims));
            } catch (Exception e) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}

4. 实现授权拦截器

实现JWT的授权拦截器,用于对用户的权限进行验证,只有拥有特定权限的用户才能访问受限资源。

可以通过继承HandlerInterceptor接口实现自定义的授权拦截器,并在preHandle方法中判断用户是否拥有权限。


public class JwtAuthorizationInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取认证信息
        JwtAuthenticationToken authentication = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        Claims claims = authentication.getCredentials();
        // 判断用户是否拥有特定权限
        if (!claims.get("roles", List.class).contains("admin")) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足");
            return false;
        }
        return true;
    }
}

通过实现自定义的认证过滤器和授权拦截器,能够很方便地在Spring Boot应用中使用JWT进行身份和权限验证。在过滤器中解析JWT令牌,并将认证信息存储到SecurityContextHolder中;在拦截器中判断用户是否拥有特定权限。这样,只需要在需要进行身份和权限验证的接口上加上相应的过滤器和拦截器即可。