Как обезопасить определенные маршруты с помощью токена и фильтров? - PullRequest
0 голосов
/ 19 марта 2019

Контекст

Я создаю приложение (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: Я надеюсь, что я ясен, если нет, спросите меня и обновите мой пост.

...