Контекст
Я создаю приложение (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
?Какой самый лучший способ?
Спасибо за вашу помощь и советы.
NB: Я надеюсь, что я ясен, если нет, спросите меня и обновите мой пост.