Spring boot + JWT 实现安全验证 ---auth0.jwt
auth0的jwt 实现安全验证: 使用自定义参数 和时间戳生成token。验证token时验证自定义参数。auth0.jwt 验证token时会自动验证时间戳是否过期,如果过期,会抛出异常TokenExpiredException
1.引入依赖
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
2.生成token和验证token的工具类
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
@Component
public class TokenUtil {
@Value("${jwt.issuer}")
private String ISSUER;//project-name
@Value("${jwt.audience}")
private String AUDIENCE;//web
@Value("${jwt.expires_in}")
private int EXPIRES_IN;//30
private String encryKey = "project-name";
private Algorithm ALGORITHM = Algorithm.HMAC256(encryKey);
private Logger logger = LoggerFactory.getLogger(this.getClass());
public static Boolean result = false;
public static String message = "";
public String generateToken(String username) {
long currentTime = System.currentTimeMillis();
logger.info("=====generateToken===now is " + new Date(currentTime));
logger.info("=====generateToken===expire is " + new Date(currentTime + EXPIRES_IN * 1000 * 60));
String token = JWT.create()
.withIssuer(ISSUER)
.withIssuedAt(new Date(currentTime))// 签发时间
.withExpiresAt(new Date(currentTime + EXPIRES_IN * 1000 * 60))// 过期时间戳
.withClaim("username", username)//自定义参数
.sign(ALGORITHM);
return token;
}
public void verifyToken(String token) {
try {
if (null == token) {
result = false;
message = "token is null";
return;
}
// Reusable verifier instance
JWTVerifier verifier = JWT.require(ALGORITHM)
.withIssuer(ISSUER)
.build();
DecodedJWT decodedJWT = verifier.verify(token);
// verify issuer
String issuer = decodedJWT.getIssuer();
// verity 自定义参数
String username = decodedJWT.getClaim("username").asString();
if (("").equals(username)) {
result = false;
message = "user is error";
return;
}
} catch (TokenExpiredException e) {
result = false;
message = "token is expired";
return;
}
result = true;
message = "token is verified";
}
}
3. 把token的生成和验证工具 添加到spring 拦截器中
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class TokenInterceptor extends HandlerInterceptorAdapter {
private TokenHelper tokenHelper;
public TokenInterceptor(TokenHelper tokenHelper) {
this.tokenHelper = tokenHelper;
}
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// verify token
tokenHelper.verifyToken(request.getHeader("token"));
// result
if (TokenHelper.result) {
return true;
} else {
response.setStatus(403);
logger.error(TokenHelper.message);
return false;
}
}
}
4.注册拦截器
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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 WebConfig implements WebMvcConfigurer {
@Autowired
private TokenHelper tokenHelper;
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
// 获取token 不要验证
excludePath.add("/api/generateToken");
registry.addInterceptor(new TokenInterceptor(tokenHelper))
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
}
}
5.生成token测试
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class TokenController {
@Autowired
private TokenHelper tokenHelper;
@PostMapping(value = "/generateToken")
public String generateToken(@RequestParam("username") String username) {
return tokenHelper.generateToken(username);
}
}
6.其它url访问项目 都需要在请求头部带着token否则会失败。