一、导入maven依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
二、导入JWT工具类 (工具类)
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;public class JwtUtil {/*** secretKey jwt秘钥*/private static String secretKey="xiaoxiaolichengxvyuan";/*** ttlMillis jwt过期时间(毫秒)* 设置有效期1天*/private static long ttlMillis=1000*3600*24;/*** 指定令牌名称,前端需要在请求头中携带tokenName*/public static String tokenName="Authorization";/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param claims 设置的信息*/public static String createJWT( Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT的时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** Token解密* @param token 加密后的token*/public static Claims parseJWT(String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}
}
三、自定义JWT拦截器 (拦截器)
import com.example.testutils.utils.JwtUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class JwtInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//从请求头获取令牌String token=request.getHeader(JwtUtil.tokenName);try {//判断是否携带令牌if (StringUtils.isEmpty(token)){throw new Exception("未携带JWT令牌");}//判断令牌是否有效if (JwtUtil.parseJWT(token)==null){throw new Exception("JWT令牌有误");}}catch (Exception e){//出现异常,拦截,设置状态码为401response.setStatus(401);return false;}return true;}
}
四、将拦截器加入配置(配置类)
import com.example.testutils.interceptor.JwtInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new JwtInterceptor()).addPathPatterns("/**")//设置不拦截的请求路径,如登录接口不需要拦截等.excludePathPatterns("/login")//我使用了Knife4j测试文档,如果你没使用,可以不配置下面这行.excludePathPatterns("/doc.html","/swagger-resources");}
}