我正在尝试实现自己的ContainerRequestFilter
并配置SecurityContext
。它在jax-rs资源上运行良好,但EJB jax-rs抛出javax.ejb.AccessLocalException
我发现只有相关的事情是4岁,而且解决方法看起来并不漂亮。 https://java.net/projects/jersey/lists/users/archive/2010-05/message/265
我的自定义SecurityContext:
@Provider
@PreMatching
public class SecurityFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext filterContext) throws IOException {
filterContext.setSecurityContext(new Authorizer());
}
public class Authorizer implements SecurityContext {
public Principal getUserPrincipal() {
return null;
}
public boolean isUserInRole(String role) {
return true;
}
public boolean isSecure() {
return false;
}
public String getAuthenticationScheme() {
return null;
}
}
经过测试的资源(不使用@Stateless)
@Path("test")
@Stateless
public class TestSecureResource {
@GET
@RolesAllowed("admin")
@Path("admin")
public Response secureTest() {
return Response.status(200).entity("admin").build();
}
}
有人知道如何使这项工作吗?
答案 0 :(得分:6)
您可以将JAX-RS SecurityContext
用作API而非SPI。应用程序开发人员提供SecurityContext
实现的情况并不常见。如果你这样做,你必须知道它只有"本地JAX-RS有效性" ,因为它是一个特定于JAX-RS的API。 Servlet / Web容器和EJB容器都不能使用它。他们没有必要,因为Java SE和EE具有更广泛的安全支持。
如果您希望安全检查在Java EE应用程序中起作用(即EJB上的HttpServletRequest.isUserInRole(...)
,EJBContext.isCallerInRole(...)
或javax.annotation.security
注释),则需要使用Java EE功能保护Servlet层。这意味着在<security-constraint>
中使用web.xml
。您可以将*
用作<role-name>
含义&#34;所有经过身份验证的&#34;用户可以调用REST API:
<security-constraint>
<web-resource-collection>
<url-pattern>/rest/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>adminRole</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<url-pattern>/rest/orders/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name> <!-- all authenticated users -->
</auth-constraint>
</security-constraint>
如上所示,当您的Java EE应用程序受到保护时,我们可以使用名为RolesAllowedDynamicFeature的Jersey特定功能在JAX-RS中启用javax.annotation.security
注释。
注册功能:
@ApplicationPath("/rest")
public class MyApplication extends ResourceConfig {
public MyApplication() {
super(AdminResource.class);
register(RolesAllowedDynamicFeature.class);
}
}
保护您的资源:
@Path("/admin")
@RolesAllowed("adminRole")
public class AdminResource {
@GET
public String get() { return "GET"; }
...
}
请参阅Jersey User guide for more details about securing JAX-RS applications。
所以你很亲密。您不需要自己实施SecurityContext
。如果处理安全的EJB,则不得实现它。最后,您需要将JAX-RS层保护为常见的Web / Servlet应用程序。我确定您已经保护了您的网页/ HTML页面。
答案 1 :(得分:1)
我终于解决了。我无法使用javax.security.RolesAllowed
,因为它的处理方式与EJB容器不同。所以我实现了自己的RolesAllowed
注释。它的缺点是它不像原始javax.security.RolesAllowed
的实现那么先进。例如,它不像here中描述的那样支持实体过滤。 Java EE社区需要在下一个Java EE 8版本中集成安全性,我希望我们能够看到更好的解决方案。
我将工作示例放在github上。
答案 2 :(得分:0)
我有同样的问题理查德,我按照下面的泽西安全指南。 https://jersey.java.net/documentation/latest/security.html#d0e10816
我使用ContainerRequestFilter进行身份验证,这里我设置了SecurityContext的自定义实现,如果身份验证成功,则rolesalloweddynamic功能将使用rolesallowed注释来授权访问特定资源。
这三个组件允许我在应用程序级别进行身份验证和授权,而不是在容器级别进行身份验证和授权
这很好用,直到我的应用程序从servlet转换为EJB / servlet(我将无状态ejb注释添加到jax-rs资源类)。 EJB使用rolesallowed注释来限制在容器级别访问其bean方法,因此它与我的应用程序级别身份验证/授权冲突。
我仍在寻找一个全面的解决方案,即使它禁用了EJB级方法安全性,因此我可以将其留给ContainerRequestFilter进行身份验证,并允许使用rolesalloweddynamicfeature进行授权。这是我关于这个问题的帖子 Client not authorized for this invocation JAX-RS EJB error