首先在pom文件中添加:
<!--jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
创建jwt工具类:
/**
* jwt工具类
*
* @author tuc
*/
@Component("jwtUtil")
public class JwtUtil {
/**
* 加密秘钥
*/
private String secret = "a1g2y47dg3dj59fjhhsd7cnewy73j";
/**
* 生成token
*
* @param user
* @return String
*/
public String generateToken(String user) {
Map<String, Object> claims = new HashMap<>(1);
claims.put("sub", user);
return generateToken(claims);
}
/**
* 生成token
*
* @param claims
* @return String
*/
private String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(this.generateExpirationDate())
.setIssuedAt(this.generateCurrentDate())
.signWith(SignatureAlgorithm.HS512, this.secret)
.compact();
}
private Date generateCurrentDate() {
return new Date(System.currentTimeMillis());
}
private Date generateExpirationDate() {
/**
* 有效时间(当前设置30天)
*/
long expiration = (long) 30 * 24 * 60 * 60 * 1000;
return new Date(System.currentTimeMillis() + expiration);
}
/**
* 判断token是否可以刷新
*
* @param token
* @param lastPasswordReset
* @return Boolean
*/
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(this.secret)
.parseClaimsJws(token)
.getBody();
final Date iat = claims.getIssuedAt();
final Date exp = claims.getExpiration();
if (iat.before(lastPasswordReset) || exp.before(generateCurrentDate())) {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
/**
* 刷新token
*
* @param token
* @return String
*/
public String refreshToken(String token) {
String refreshedToken;
try {
final Claims claims = Jwts.parser()
.setSigningKey(this.secret)
.parseClaimsJws(token)
.getBody();
refreshedToken = this.generateToken(claims);
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}
/**
* 校验token
*
* @param token
* @return TokenStatus
*/
public TokenStatus verifyToken(String token) {
TokenStatus result;
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(this.secret)
.parseClaimsJws(token)
.getBody();
final Date exp = claims.getExpiration();
if (exp.before(generateCurrentDate())) {
result = TokenStatus.EXPIRED;
} else {
result = TokenStatus.VALID;
}
} catch (Exception e) {
result = TokenStatus.INVALID;
}
return result;
}
/**
* 获取用户编号
*
* @param token
* @return Integer
*/
public String getUserNameFromToken(String token) {
String userName;
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(this.secret)
.parseClaimsJws(token)
.getBody();
userName = claims.getSubject();
} catch (Exception e) {
userName = null;
}
return userName;
}
}
token状态枚举类:
/**
* token状态
*
* @author tuc
*/
public enum TokenStatus {
/**
* 过期的
*/
EXPIRED("EXPIRED"),
/**
* 无效的
*/
INVALID("INVALID"),
/**
* 有效的
*/
VALID("VALID");
private final String status;
TokenStatus(String status) {
this.status = status;
}
public String value() {
return this.status;
}
}
创建jwt过滤器:
/**
* jwt过滤器
*
* @author tuc
*/
@Component
public class JwtFilter implements Filter {
/**
* 排除拦截的请求
*/
private String[] excludedPages = {"/login"};
private static Logger logger = LoggerFactory.getLogger(JwtFilter.class);
private JwtUtil jwtUtil = new JwtUtil();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
for (String page : excludedPages) {
if (httpRequest.getRequestURI().equals(page)) {
chain.doFilter(httpRequest, httpResponse);
return;
}
}
String token = httpRequest.getHeader(Constants.TOKEN_HEADER);
TokenStatus tokenStatus = jwtUtil.verifyToken(token);
switch (tokenStatus) {
//有效
case VALID:
String user = jwtUtil.getUserNameFromToken(token);
httpRequest.setAttribute(Constants.LOGIN_USER, user);
chain.doFilter(httpRequest, httpResponse);
break;
//无效
case INVALID:
accessDeny(httpResponse, 1);
break;
//过期
case EXPIRED:
accessDeny(httpResponse, 2);
break;
default:
accessDeny(httpResponse, 1);
break;
}
} catch (Exception e) {
logger.error("jwtFilter Exception: {}", e.getMessage());
accessDeny(httpResponse, 1);
}
}
/**
* token 校验失败提示
*
* @param type 1无效,2过期
*/
private void accessDeny(HttpServletResponse response, int type) {
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
writer = response.getWriter();
ResultModel resultModel = new ResultModel();
if (1 == type) {
resultModel = ResultTools.result(1001, "", null);
} else if (2 == type) {
resultModel = ResultTools.result(1002, "", null);
}
JSONObject jsonObject = new JSONObject(resultModel);
writer.print(jsonObject);
} catch (IOException e) {
System.out.print(e.getMessage());
} finally {
if (writer != null) {
writer.close();
}
}
}
@Override
public void init(FilterConfig filterConfig) {
logger.info("jwtFilter init ...");
}
@Override
public void destroy() {
logger.info("jwtFilter destroy ...");
}
}
配置过滤规则:
/**
* 配置类
*
* @author tuc
*/
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Bean
public FilterRegistrationBean jwtFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new JwtFilter());
registration.setName("JwtFilter");
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE", "PATCH")
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "x-auth-token")
.allowCredentials(false).maxAge(3600);
}
}
到这里基本已配置完成,下面为使用示例:
创建TestController:
/**
* 测试Controller
*
* @author tuc
*/
@RestController
public class TestController {
@Autowired
private JwtUtil jwtUtil;
/***
* 测试登录
* 这里使用用户id来生成token
*/
@PostMapping("/login")
public ResultModel login(Integer userId) {
try {
Map<String, Object> map = new HashMap<>(1);
map.put("token", jwtUtil.generateToken(userId + ""));
return ResultTools.result(0, "", map);
} catch (Exception e) {
return ResultTools.result(404, e.getMessage(), null);
}
}
/***
* 测试jwt验证
*/
@GetMapping("/api/test")
public ResultModel getTest(HttpServletRequest request) {
try {
String user = request.getAttribute(Constants.LOGIN_USER).toString();
Map<String, Object> map = new HashMap<>(1);
map.put("user", user);
return ResultTools.result(0, "", map);
} catch (Exception e) {
return ResultTools.result(404, e.getMessage(), null);
}
}
}
启动项目,调用http://localhost:8080/api/test 不传任何参数,结果如下
表示接口已被拦截,token无效或是没传。
接下来我们做正确的操作:
先调用http://localhost:8080/login?userId=66 拿到用户token(假设用户id=66)
然后重新调用http://localhost:8080/api/test,这次我们带上token请求头
至此验证成功....
最后附上源码下载地址:https://download.csdn.net/download/qq_29370483/11192238