1.导入依赖
<!--Jwt--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency
2.Jwt工具类
package com.zhang.common.utils; import com.alibaba.fastjson2.JSON; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; import java.util.Date; import java.util.UUID; @Component public class JwtUtil { // 有效期 private static final long JWT_EXPIRE = 30*60*1000L; //半小时 // 令牌秘钥 private static final String JWT_KEY = "123456"; public String createToken(Object data){ // 当前时间 long currentTime = System.currentTimeMillis(); // 过期时间 long expTime = currentTime+JWT_EXPIRE; // 构建jwt JwtBuilder builder = Jwts.builder() .setId(UUID.randomUUID()+"") .setSubject(JSON.toJSONString(data)) .setIssuer("system") .setIssuedAt(new Date(currentTime)) .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY)) .setExpiration(new Date(expTime)); return builder.compact(); } private SecretKey encodeSecret(String key){ byte[] encode = Base64.getEncoder().encode(key.getBytes()); SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES"); return aes; } public Claims parseToken(String token){ Claims body = Jwts.parser() .setSigningKey(encodeSecret(JWT_KEY)) .parseClaimsJws(token) .getBody(); return body; } public <T> T parseToken(String token,Class<T> clazz){ Claims body = Jwts.parser() .setSigningKey(encodeSecret(JWT_KEY)) .parseClaimsJws(token) .getBody(); return JSON.parseObject(body.getSubject(),clazz); } }
3.关键代码
//创建jwt String token = jwtUtil.createToken(loginUser);//解析jwt
user = jwtUtil.parseToken(token, User.class);
4.前端发送请求前对token进行校验,解决token错了还能发送请求的BUG
package com.zhang.interceptor; import com.alibaba.fastjson2.JSON; import com.zhang.common.utils.JwtUtil; import com.zhang.common.vo.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component @Slf4j public class JwtValidateInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token=request.getHeader("X-token"); log.debug(request.getRequestURI()+"需要验证:"+token); if(token!=null){ try { jwtUtil.parseToken(token); log.debug(request.getRequestURI()+"验证通过");//在生产环境中只要日志级别高于debug这段代码就会被屏蔽,不建议写sout(被称为垃圾代码) return true;//放行 } catch (Exception e) { throw new RuntimeException(e); } } log.debug(request.getRequestURI()+"验证失败禁止访问"); response.setContentType("application/json;charset=utf-8"); Result<Object> fail = Result.fail(20003, "jwt无效,请重新登录"); response.getWriter().write(JSON.toJSONString(fail)); return false;//拦截 } }
5.添加拦截器,解决未登录还能发送其他请求,同时将token校验添加到拦截器中
package com.zhang.config; import com.zhang.interceptor.JwtValidateInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class MyInterceptorConfig implements WebMvcConfigurer { @Autowired private JwtValidateInterceptor jwtValidateInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { InterceptorRegistration registration = registry.addInterceptor(jwtValidateInterceptor); //定义拦截规则 registration.addPathPatterns("/**")//拦截所有 .excludePathPatterns("/user/login",//排除拦截的路径 "/user/info", "/user/logout"); } }