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否則會失敗。
