第一步:引入pom文件
<!--安全框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--jwt加密--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.6.0</version> </dependency>
第二步:在启动类同路径下创建WebConfiguration 添加拦截器
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
//注册拦截器
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor) //注册拦截器
.addPathPatterns("/**") //拦截一切请求(任何请求路径)
.excludePathPatterns("/**/login");//放过login登录请求
}
}
第三步:自定义拦截器
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private JwtUtils jwtUtils;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("经过了拦截器");
//获得放置token的请求头
String token = request.getHeader("Authorization");
//校验头格式
if(StringUtils.isEmpty(token) || !token.startsWith("Bearer ")){
throw new RuntimeException("请先登录");
}
//截取token字符串
token = token.substring(7);
//解析token
try {
Claims claims = jwtUtils.parseToken(token);
request.setAttribute("claims",claims);
} catch (Exception e) {
throw new RuntimeException("请先登录");
}
return true;
}
}
第四步:引入jwt工具类
工具类要在启动类注入一下
@Bean public JwtUtils getJwtUtils(){ return new JwtUtils(); }
public class JwtUtils {
//配置文件配置的
@Value("${jwt.ttl}")
private long ttl; //指定token有效时间 (小时)
//密钥
@Value("${jwt.secret}")
private String secret;
//生成Token
public String buildToken(String userId, String userName){
long currentTimeMillis = System.currentTimeMillis(); //当前系统时间
long expirationTimeMillis = currentTimeMillis + 1000*60*60*ttl; //过期时间
String token = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, secret)//指定加密算法和密钥
.setId(userId) //添加载荷部分键值对 => 放置登录用户id
.setSubject(userName) //添加载荷部分键值对 => 放置登录用户名
.setIssuedAt(new Date()) //添加载荷部分键值对 => 放置签发token时间
.setExpiration(new Date(expirationTimeMillis))//指定token的过期时间
.compact();//生成密文token
return token;
}
//解析Token
public Claims parseToken(String token){
Claims claims = Jwts.parser() //返回token解析器
.setSigningKey(secret) //指定解析使用的密钥 => 需要跟加密时使用相同的密钥
.parseClaimsJws(token) // 指定要解密的Token
.getBody();//获得载荷部分
return claims;
}
}
第五步:请求类
@Autowired
private JwtUtils jwtUtils;
@RequestMapping(value = "/login",method = RequestMethod.POST)
public R login(//前端输入的账号和密码@RequestParam("userId") String userId,@RequestParam("passWord") String passWord){
//通过账号密码去数据库查数据 获取用户的信息
String token = jwtUtils.buildToken("用户id", "用户名称");
//R是封装的返回实体
}
token 这就拿到了,前端每次请求都需要携带着token,然后拦截器就会拦截请求校验token,成功才进请求,失败就返回错误信息。
踩坑需要注意的地方:前端每次请求会有一个预检options请求,要在拦截器过滤掉这个请求
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
return true;
}