gpt4 book ai didi

java - 如何在 Jersey 中保护程序化资源?

转载 作者:行者123 更新时间:2023-11-30 06:48:47 24 4
gpt4 key购买 nike

Jersey JAX-RS 资源可以使用这样的注释来保护。

@RolesAllowed("user")
@GET
public String get() { return "GET"; }

我的要求是保护我这样创建的动态创建的 Jersey 资源

@ApplicationPath("/")
public class MyApp extends ResourceConfig {
public MyApp() {

packages("com.test.res");
Resource.Builder resourceBuilder = Resource.builder();
resourceBuilder.path("/myresource3");

final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET");
methodBuilder.produces(MediaType.TEXT_PLAIN).handledBy(new TestInflector());

Resource resource = resourceBuilder.build();
registerResources(resource);
register(RolesAllowedDynamicFeature.class);
}

}

如何只允许“用户”访问这个动态创建的资源?

最佳答案

不幸的是,RolesAllowedDynamicFeature 似乎不支持使用编程 API 创建的资源。如果您查看 source for RolesAllowedDynamicFeature ,您会看到它查找资源方法和/或资源类上的注释以确定资源/方法是否应附加到 filter that handles the authorization .

我能想到的最好的方法就是在 Inflector 中进行授权。你可以看到我链接到的源代码,处理授权的过滤器并没有做太多事情。它只是检查 SecurityContext 是否允许角色。您可以在 Inflector 中使用逻辑。例如

public static class AuthorizationInflector
implements Inflector<ContainerRequestContext, Response> {

private final String[] rolesAllowed;
private final Inflector<ContainerRequestContext, Response> delegate;

protected AuthorizationInflector(String[] rolesAllowed,
Inflector<ContainerRequestContext, Response> delegate) {
this.rolesAllowed = (rolesAllowed != null) ? rolesAllowed : new String[] {};
this.delegate = delegate;
}

@Override
public Response apply(ContainerRequestContext context) {
applyAuthorization(context);

return this.delegate.apply(context);
}


private void applyAuthorization(ContainerRequestContext requestContext) {
if (rolesAllowed.length > 0 && !isAuthenticated(requestContext)) {
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
}

for (final String role : rolesAllowed) {
if (requestContext.getSecurityContext().isUserInRole(role)) {
return;
}
}
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
}

private static boolean isAuthenticated(final ContainerRequestContext requestContext) {
return requestContext.getSecurityContext().getUserPrincipal() != null;
}
}

它看起来与 RolesAllowedRequstFilter 中的代码非常相似。我们正在处理授权,然后将返回委托(delegate)给另一个 Inflector。你会像这样使用它

final String[] rolesAllowed = {"USER"};
methodBuilder.produces(MediaType.TEXT_PLAIN_TYPE)
.handledBy(new AuthorizationInflector(rolesAllowed, new TestInflector()));

唯一真正明显的行为差异(使用变形器而不是过滤器)是过滤器具有顺序优先级的概念。您可以在 RolesAllowedRequestFilter 中看到它使用 Priorities.AUTHORIZATION 的优先级。它使用它的原因是因为在此过滤器之前发生的身份验证过滤器应该使用优先级 Priorities.AUTHENTICATION,这确保身份验证在授权之前发生。

在使用变形器的情况下,您仍然有这个顺序,即身份验证过滤器发生在变形器应用之前。行为的不同之处在于你想实现一些其他过滤器,你希望它在授权后执行,所以你可能有这个

@Priority(Priorities.AUTORIZATION + 100)
class SomeFilter implements ContainerRequestFilter {}

也许您需要对用户进行授权。使用变形器时的问题是它不会在该过滤器之后 之前被调用。这不是您想要的,因为它取决于完成的授权。

这是使用变形器进行授权的一个缺点。

我能想到的另一件事可能可行(尽管我还没有将所有部分放在一起,就是使用名称绑定(bind)。

@NameBinding
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorization {}

methodBuilder
.nameBinding(Authorization.class)
.produces(MediaType.TEXT_PLAIN)
.handledBy(new TestInflector());

@Authorization
public class AuthorizationFilter implements ContainerRequestFilter {}

您可以像RolesAllowedRequestFilter 一样实现AuthorizationFilter。我还没有弄清楚的是如何从过滤器内部获得允许的角色。您显然不能只将它传递给过滤器,因为它需要根据资源方法确定范围。我不确定这是否可以完成。这是我需要进一步研究的东西。

目前,我唯一能想到的我已经测试过并且有效的方法就是使用变形器。

关于java - 如何在 Jersey 中保护程序化资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43793385/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com