永远不会调用JAX-RS Provider的过滤方法

时间:2017-12-25 17:55:38

标签: java annotations jersey jax-rs

我尝试了this教程并实现了示例中给出的Provider类。

@Provider
@Secured
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    private static final String REALM = "example";
    private static final String AUTHENTICATION_SCHEME = "Bearer";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // Get the Authorization header from the request
        String authorizationHeader =
                requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        // Validate the Authorization header
        if (!isTokenBasedAuthentication(authorizationHeader)) {
            abortWithUnauthorized(requestContext);
            return;
        }

        // Extract the token from the Authorization header
        String token = authorizationHeader
                            .substring(AUTHENTICATION_SCHEME.length()).trim();

        try {

            // Validate the token
            validateToken(token);

        } catch (Exception e) {
            abortWithUnauthorized(requestContext);
        }
    }

    private boolean isTokenBasedAuthentication(String authorizationHeader) {

        // Check if the Authorization header is valid
        // It must not be null and must be prefixed with "Bearer" plus a whitespace
        // The authentication scheme comparison must be case-insensitive
        return authorizationHeader != null && authorizationHeader.toLowerCase()
                    .startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
    }

    private void abortWithUnauthorized(ContainerRequestContext requestContext) {

        // Abort the filter chain with a 401 status code response
        // The WWW-Authenticate header is sent along with the response
        requestContext.abortWith(
                Response.status(Response.Status.UNAUTHORIZED)
                        .header(HttpHeaders.WWW_AUTHENTICATE, 
                                AUTHENTICATION_SCHEME + " realm=\"" + REALM + "\"")
                        .build());
    }

    private void validateToken(String token) throws Exception {
        // Check if the token was issued by the server and if it's not expired
        // Throw an Exception if the token is invalid

        //TODO validate against database
        if(!token.equals("exampleString")) {
            throw new AuthenticationException("Invalid token.");
        }
    }
}

服务器也可以识别此Provider类,可以在日志中看到:

Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Root resource classes found:
  class com.jwt.service.AuthenticationEndpoint
  class com.jwt.service.HelloWorldService
Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Provider classes found:
  class com.jwt.service.AuthenticationFilter

我为注释创建了一个接口:

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
}

还注释了我的REST端点。

@GET
@Path("/secured")
@Secured
public Response getUserSecured() {
    return Response.status(200).entity("Secured getUser is called").build();
}

即使我的Provider类被识别,但在调用带注释的方法时它仍然没有做任何事情。即使没有发送身份验证,也不会输出未经授权的状态代码,而是返回“安全的getUser被调用”。

有人知道为什么我的Provider类的filter方法从未被调用过吗?

1 个答案:

答案 0 :(得分:1)

com.sun.jersey.api包(在提供的日志中可见)是Jersey 1,而您正在关注的教程涉及球衣2。 升级到泽西岛2,它将起作用。