如果以不安全的方式访问某些方法,我想对其进行限制。我正在创建一个 @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/