如何使用令牌和过滤器保护特定路由?

时间:2019-03-18 21:08:11

标签: java spring spring-boot spring-security jwt

上下文

我正在做一个应用程序(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?最好的方法是什么?

感谢您的帮助和建议。

注意:我希望我很清楚,如果不是,请问我,并会更新我的帖子。

0 个答案:

没有答案