是否可以在 JAX-WS Web 服务上使用 @RolesAllowed
注释?如果可以,如何使用?
我在 glassfish 3.1.1 上有一个使用基本身份验证的 Web 服务,但使用 @RolesAllowed
表达的限制将被忽略。角色信息应该可用,因为我可以像这样访问它:
@Resource
WebServiceContext wsContext;
if (wsContext.isUserInRole("READ"))
log.info("Role: READ");
我获得了预期的角色,但仍然可以访问所有方法,即使 @RolesAllowed
设置为不同的角色。 @DenyAll
也不起作用。
如果不支持这些注释,是否可以使用部署描述符来根据用户角色管理对 Web 服务方法的访问?
编辑:
JAVA EE 6 教程的这部分介绍了 @ 的用法RolesAllowed
注释。上面写着
对于 Java EE 组件,您可以使用 @DeclareRoles 和 @RolesAllowed 元数据注释定义安全角色。
在本教程的第一部分中,Web 服务没有被列为 Java EE 组件,因此看起来安全注释不受支持。
编辑2
继 Izan 的帖子之后,我再次尝试。这就是我所做的:
@Webservice
@DeclareRoles(value = {"READ", "UPDATE", "DELETE"})
public class ServiceImpl implements Service {
@Override
@WebMethod(operationName = "helloWorld")
@RolesAllowed({"NONE"})
public String helloWorld() throws Exception {
return "Hello World!";
}
}
使用这种设置,每个人都可以访问该方法,无论设置什么角色。用户获得身份验证(可以在audit.log 中看到),但不会进行授权。如上所述,我可以从 WebServiceContext
访问该角色(实际上我使用此信息进行手动授权)。
添加 @Stateless
注释,让我使用安全注释。所以 @permitAll
按预期工作。但是使用角色仍然不起作用,因为用户现在没有经过身份验证。它们在审核日志中显示为ANONYMOUS
,并且访问被拒绝。
我的 web.xml
如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>OneMore</display-name>
<security-constraint>
<display-name>WebServiceSecurity</display-name>
<web-resource-collection>
<web-resource-name>Authorized users only</web-resource-name>
<url-pattern>/service</url-pattern>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>READ</role-name>
<role-name>UPDATE</role-name>
<role-name>DELETE</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>READ</role-name>
</security-role>
<security-role>
<role-name>UPDATE</role-name>
</security-role>
<security-role>
<role-name>DELETE</role-name>
</security-role>
</web-app>
Glassfish-web.xml
只是将角色名称映射到组名称,如下所示:
<security-role-mapping>
<role-name>READ</role-name>
<group-name>READ</group-name>
</security-role-mapping>
编辑 3
感谢 Izan 和无数次的尝试,我终于成功了。
如前所述,要点是通过添加 @Stateless 注释从普通 Web 服务切换到 EJB Web 服务。这允许使用安全注释。
此更改还需要更改部署描述符。虽然原始 Web 服务需要 glassfish-web.xml
来设置角色,但之后还需要 glassfish-ejb-jar.xml
。
Is it possible to use @RolesAllowed
annotation on a JAX-WS webservice and if so how?
I have a webservice on glassfish 3.1.1 using Basic Authentication but restrictions expressed using @RolesAllowed
are ignored. The role information should be available, as I can access it like this:
@Resource
WebServiceContext wsContext;
if (wsContext.isUserInRole("READ"))
log.info("Role: READ");
I get the expected role but still all methods are accessible, even if @RolesAllowed
is set to different role. @DenyAll
is not working as well.
If these annotations are not supported, is it possible to use deployment descriptors to manage access to webservice methods based on user roles?
Edit:
This part of the JAVA EE 6 tutorial describes the usage of @RolesAllowed
annotation. It reads
For Java EE components, you define security roles using the @DeclareRoles and @RolesAllowed metadata annotations.
Web services are not listed as Java EE components in the first part of the tutorial, so it looks like the security annotations are not supported.
Edit2
Following Izan's post, I gave this another try. Here is what I did:
@Webservice
@DeclareRoles(value = {"READ", "UPDATE", "DELETE"})
public class ServiceImpl implements Service {
@Override
@WebMethod(operationName = "helloWorld")
@RolesAllowed({"NONE"})
public String helloWorld() throws Exception {
return "Hello World!";
}
}
Using this kind of setup, everybody can access the method, no matter what roles are set. Users get authenticated (can see that in audit.log) but no authorization takes place. As stated above, I can access the role from WebServiceContext
(I actually do manual authorization using this info).
Adding @Stateless
annotation, let's me use the security annotations. So @permitAll
works as expected. But using roles still does not work, as user don't get authenticated now. They show up as ANONYMOUS
in audit log and access is denied to them.
My web.xml
looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>OneMore</display-name>
<security-constraint>
<display-name>WebServiceSecurity</display-name>
<web-resource-collection>
<web-resource-name>Authorized users only</web-resource-name>
<url-pattern>/service</url-pattern>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>READ</role-name>
<role-name>UPDATE</role-name>
<role-name>DELETE</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>READ</role-name>
</security-role>
<security-role>
<role-name>UPDATE</role-name>
</security-role>
<security-role>
<role-name>DELETE</role-name>
</security-role>
</web-app>
Glassfish-web.xml
just maps role names to group names, like this:
<security-role-mapping>
<role-name>READ</role-name>
<group-name>READ</group-name>
</security-role-mapping>
Edit 3
Thanks to Izan and countless tries later I finally got it working.
As said before, the main point was switching from a plain web service to an EJB web service by adding @Stateless
annotation. This allows for using the security annotations.
This change required to change the deployment descriptors as well. While the original web service required a glassfish-web.xml
for setting up the roles, a glassfish-ejb-jar.xml
is required afterwards.
发布评论
评论(2)
也许这是一个非常愚蠢的问题,但是您的 Web 服务是 EJB 吗?如 GlassFish 和 Java EE 5 SDK 中的安全注释和授权中所述
我将这些注释与来自无状态 EJB 的自下而上 WS 一起使用,它们在 JBoss 中的工作方式就像一个魅力。
编辑1 @TPete
我将添加一些代码来或多或少地向您展示我在做什么。
至于接口
WebContext、EndpointConfig 和 SecurityDomain 是 JBoss 注释,但我认为 GlassFish 也有类似的东西,或者等效的方法。安全域包含在 jboss 的部署描述符中,并在 JBoss 配置文件的 login-config.xml 中定义。
编辑2 @TPete
我想您需要从 Glassfish 添加一些 EJB 部署描述符,Glassfish 是 EAR 内的一个 sun-ejb-jar.xml 文件包。同样,在答案中发布的同一篇文章中,有一个使用部署描述符章节指出
由于您正在定义 EJB Web 服务端点,因此我认为您应该将此描述符放入 EAR 中。快速浏览一下那篇文章,它很好地描述了您正在遵循的过程:-)
Maybe this is a pretty dumb question, but are your webservices EJBs? As noted in Security Annotations and Authorization in GlassFish and the Java EE 5 SDK
I use those annotations with bottom-up WS from stateless EJBs and they work like a charm in JBoss.
EDIT 1 @TPete
I'll add some code to show you more or less what I'm doing.
And as for the interface
WebContext, EndpointConfig and SecurityDomain are JBoss annotation, but I suppose there is something similar for GlassFish, or an equivalent way of doing it. The security domain is included in a deployment descriptor for jboss, and defined in the login-config.xml from the configuration files of JBoss.
EDIT 2 @TPete
I suppose you need to add some EJB deployment descriptors from Glassfish, a sun-ejb-jar.xml file package inside your EAR. Again, from the same article as posted in the answer, there is a Using Deployment Descriptors chapter that states
Since you are defining an EJB web service endpoint, I think you should put this descriptor in you EAR. Have a quick look at that article, it describes quite well the process you are following :-)
最初的问题已经很老了,但我仍然留下评论,以防像我这样的人偶然发现它。从 EJB 3.1 开始,EJB 可以打包在 WAR 模块中,但在保护它们时,需要使用 EJB 部署描述符。规范中没有明确的是,EJB 不得在 web.xml 中声明为 Servlet,否则应用程序将无法启动。
这是一篇关于在 WAR 模块中打包 EJB 以及与在 EJB JAR 模块中打包的区别的优秀文章:
http://pic.dhe.ibm.com/infocenter/wasinfo/v8r0/index.jsp?topic=%2Fcom.ibm.websphere.nd.multiplatform.doc%2Finfo%2Fae%2Fae%2Fcejb_ejbinwar .html
The original question is old but I'm still leaving a comment just in case someone like me stumbles across it. Starting with EJB 3.1, EJBs may be packaged in a WAR module but when it comes to securing them, EJB deployment descriptors need to be used. What is not clear in the spec is that EJBs may not be declared as Servlets in web.xml or else the app will fail to start.
Here's an excellent article about packaging EJBs in WAR modules and the differences with packaging in EJB JAR modules:
http://pic.dhe.ibm.com/infocenter/wasinfo/v8r0/index.jsp?topic=%2Fcom.ibm.websphere.nd.multiplatform.doc%2Finfo%2Fae%2Fae%2Fcejb_ejbinwar.html