java - 使用 Jersey 的 AbstractHttpContextInjectable 的自定义方法注释不起作用

标签 java annotations jersey dropwizard

如果以不安全的方式访问某些方法,我想对其进行限制。我正在创建一个 @Secure 注释来检查请求是否通过安全通道发送。但是,我无法创建捕获请求的 HttpContext 的可注入(inject)方法。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Secure {

}

public class SecureProvider<T> implements InjectableProvider<Secure, AbstractResourceMethod> {
    @Override
    public ComponentScope getScope() {
        return ComponentScope.PerRequest;
    }

    @Override
    public Injectable<?> getInjectable(ComponentContext componentContext,
                                       Secure annotation,
                                       AbstractResourceMethod method) {
        return new SecureInjectable();
    }
}

public class SecureInjectable<T> extends AbstractHttpContextInjectable<T> {
    @Override
    public T getValue(HttpContext context) {    
        // validation here

        return null;
    }
}

我正在使用 Dropwizard 框架,因此 Provider 的初始化应该很简单:

environment.addProvider(new SessionRestrictedToProvider<>(new SessionAuthenticator(), "MySession"));
environment.addProvider(new SecureProvider<>());
environment.setSessionHandler(new SessionHandler());

用法:

@Resource
@Path("/account")
public class AccountResource {
    @GET
    @Path("/test_secure")
    @Secure
    public Response isSecure() {
        return Response.ok().build();
    }
}

在这一点上,我假设 HttpContext Injectable 不适用于某个方法,但我不知道我可以利用哪些其他选项来实现此注释。

最佳答案

编辑 这适用于 JAX-RS 2.0。虽然 Jersey 现在是 2.4.1 版,但遗憾的是 Dropwizard 仍在使用 1.17.1 :(。

您可以将 ContainerRequestFilter 与注释一起使用。

首先是注解:

// need a name binding annotation
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Secure { }

接下来,过滤器:

// filter will only be run for methods that have @Secure annotation
@Secure
public class SecureFilter implements ContainerRequestFilter
{
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException
    {
        // check if HTTPS
        if (!requestContext.getSecurityContext().isSecure())
        {
            // if not, abort the request
            requestContext.abortWith(Response.status(Response.Status.BAD_REQUEST)
                                             .entity("HTTPS is required.")
                                             .build());
        }
    }
}

最后,注册过滤器。这取决于您如何设置 Jersey 应用程序。这里有两种您可能已经设置过的方法,但还有许多其他可能性,因此我不会一一介绍。

如果你有一个带有 grizzly 的 ResourceConfig,你会想要这个:

final ResourceConfig rc = new ResourceConfig()
            .packages("my.package.for.resources")
            .register(SecureFilter.class);

如果您使用的是自定义应用程序模型:

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        packages("my.package.for.resources");
        register(SecureFilter.class);
    }
}

用法:

@Resource
@Path("/account")
public class AccountResource {

    // filter will run for this method
    @GET
    @Path("/test_secure")
    @Secure
    public Response isSecure() {
        return Response.ok().build();
    }

    // filter will NOT run for this method
    @GET
    @Path("/test_insecure")
    public Response allowInsecure() {
        return Response.ok().build();
    }
}

关于java - 使用 Jersey 的 AbstractHttpContextInjectable 的自定义方法注释不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19785001/

相关文章:

java - 通过单选按钮将选定的字符串传递给另一个 Activity

java - 如何依赖:tree on a specific artifact?

java - 有意义的容器元素示例

java - 如何通过反射从方法中获取注解

java - 检测服务何时将在 CloudBees 上 hibernate

java - 如何为 N-Queen Hill Climbing 生成邻居

java - Android:将普通菜单转换为 slider 菜单? (用最少的编码)

java - Hibernate Annotations/JPA 映射集合

rest - 在 jersey 1.8 和 tomcat 7 Resful 和 eclipse 中找不到 404

java - 在 WebLogic12.2.1 中禁用 WADL