JAX-RS身份验证筛选器不是通过@Secured批注

时间:2017-08-21 17:03:16

标签: java rest web-services authentication jax-rs

我正在按照以下答案:Best practice for REST token-based authentication with JAX-RS and Jersey来实现REST API身份验证。但是JAX-RS身份验证过滤器不是通过@Secured注释触发的。

我通过在方法上添加@Secured来完成保护您的REST端点部分。

这就是我这样做的方式。

Secured.java

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

AuthenticationFilter.java

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

    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 {
            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
        // 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
        // The "WWW-Authenticate" is sent along with the response
        requestContext.abortWith(
                Response.status(Response.Status.UNAUTHORIZED)
                    .header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME)
                    .build());
    }

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

MyApis.java

@Path("api")
public class MyApis {

    @GET
    @Secured
    @Path("me")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, X500Name> whoAmI() {
        return ImmutableMap.of("me", legalName);
    }

    // other APIs
}

当我拨打/api/me时,我可以直接获得响应而不提供任何身份验证标头。似乎过滤器未被触发或未正确注册。

我已经看到了这个问题JAX RS, my filter is not working,但它并没有解决我的问题。

我理解以下内容是web.xml不需要吗?

  

此解决方案仅使用JAX-RS 2.0 API,避免任何特定于供应商的解决方案。因此,它应该与最流行的JAX-RS 2.0实现一起使用,例如Jersey,RESTEasy和Apache CXF。

     

重要的是,如果您使用基于令牌的身份验证,则不依赖于servlet容器提供的标准Java EE Web应用程序安全机制,并且可以通过应用程序的web.xml描述符进行配置。

1 个答案:

答案 0 :(得分:1)

最后一个答案,但是解决此问题的方法是将AuthenticationFilter添加到您的类中。

google.visualization.drawChart