上下文
我正在做一个应用程序(REST API),我尝试增加一些安全性。
当前代码
所以我创建了两个方法:
public class Security {
private final static String apiKey = "secretkey";
// generate a token when data is created
public static String generateToken(String dataid) {
return Jwts.builder()
.setSubject(dataid)
.setIssuedAt(new Date())
.claim("roles", "user")
.signWith(SignatureAlgorithm.HS256, apiKey).compact();
}
// verify that user can access to data. He can access only if token is correct.
public static ResponseEntity<?> checkToken(String id, ServletRequest servletRequest, ServletResponse servletResponse) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
Optional<String> token = Optional.ofNullable(request.getHeader(HttpHeaders.AUTHORIZATION));
if(token.isPresent() && token.get().startsWith("Bearer ")) {
String bearerToken = token.get().substring(7);
Jws<Claims> claims = Jwts.parser().setSigningKey(apiKey).parseClaimsJws(bearerToken);
String dataid = claims.getBody().getSubject();
if(dataid.equals(id))
return new ResponseEntity<>(HttpStatus.OK);
else
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
客观
但是现在我的目标是在以data/{id}
开头的路由之前检查令牌是否正确,其中{id}
与checkToken(...)
的参数相同。
想法
我的第一个想法是为每个需要安全性的路由执行以下代码:
@GetMapping(value = "/data/{id}")
public ResponseEntity<?> test(@PathVariable("id") String id, ServletRequest servletRequest, ServletResponse servletResponse) {
ResponseEntity<?> checkToken = Security.checkToken(id, servletRequest, servletResponse);
if(checkToken.getStatusCode() != HttpStatus.OK)
return checkToken;
...
}
@GetMapping(value = "/data/{id}/users")
public ResponseEntity<?> test(@PathVariable("id") String id, ServletRequest servletRequest, ServletResponse servletResponse) {
ResponseEntity<?> checkToken = Security.checkToken(id, servletRequest, servletResponse);
if(checkToken.getStatusCode() != HttpStatus.OK)
return checkToken;
...
}
...
但是,如果我的应用程序有100条路线,我将复制100倍的代码...这是个糟糕的主意...
问题
有一种方法可以正确地做到这一点?使用Filter
吗? Interceptor
?最好的方法是什么?
感谢您的帮助和建议。
注意:我希望我很清楚,如果不是,请问我,并会更新我的帖子。