2


我的问题是 “我可以在 CXF 上实现的 RESTful 资源上使用 @RolesAllowed 吗?” .

首先,我解释一下导致这个问题的背景。
我在一些项目中工作,在这些项目中,开发人员必须将一些 Web 系统的一部分重新制作成RESTfulWEB APIs。本系统具有由Spring和构建的服务器系统Hibernate。其作为 UI 的客户端应用程序是由ActionScriptthrough 开发的FLEX framework
现在我正在研究RESTful APIs通过阅读一些文档或开发一些原型来设计和改造我们现有系统的正确方法。所以,我们暂时决定将其Apache-CXF ver.2.7.4用作JAX-RS实现和TOMCAT ver.7Web应用程序容器。

然后,我现在正在为用户授权的方式而苦苦挣扎。如你所知,我的意思是这个词'Authorization'作为一些控制机制,根据用户的滚动来约束一些用户访问功能ROLE_ADMINROLL_EMPLOYEE等等。而我们的团队希望使用@RolesAllowed注解来约束用户访问REST资源类中的一些 RESTful 方法。
通过调查,我知道如果我们使用as impl 和 TOMCAT可以使用@RolesAllowed注解,因为 Jersey 框架提供JerseyJAX-RS

com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory
供开发人员通过在 web.xml 中添加以下行来激活 @RolesAllowed 注释

<init-param>
  <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name> 
  <param-value>
    com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory
  </param-value>
</init-param>

作为 jersey 的 ServletContainer 的 init-param。

但是我们的团队决定Apache CXF采用 JAX-RS。我已经调查了 CXF 站点中 Web 文档的安全和授权部分。但我无法获得解决方案或如何使用@RolesAllowedRESTful 资源方法。

因此,如果您知道在and@RolesAllowed上实现的 RESTful 资源的要求或如何使用,请教我。或者如果您可以明确断定我们不能在框架中使用and的选择,请教我该结论的背景知识.Apache CXFTOMCAT@RolesAllowedApache CXFTOMCAT

此外,我想我可以通过on作为应用服务器@RolesAllowed在 REST 资源中使用,而不是在. 这个假设是真的吗?很抱歉,我没有尝试使用TOMCAT 来代替。CXFJBOSSTOMCATJBOSS

此致。

4

1 回答 1

4

是的,这是可以做到的。我假设您(像我一样)不想使用 Spring Security 作为解决方案的一部分(处理身份验证和授权),因为似乎有很多资源可以说明如何使用 Spring Security 启用 JSR-250 注释.

我的解决方案从一个简单的 JAX-RS 项目开始,该项目是从 CXF 提供的 Archetype 项目org.apache.cxf.archetype:cxf-jaxrs-service:2.7.5(最新的 GAV @ 写作时间)构建的。

这为您提供了一个HelloWorld带有支持配置文件的基本类。

需要进行一些修改。

首先,将以下依赖项添加到pom.xml

<dependency>
  <groupId>javax.annotation</groupId>
  <artifactId>jsr250-api</artifactId>
  <version>1.0</version>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.0.1</version>
  <scope>provided</scope>
</dependency>   

为什么?因为 Tomcat 不是一个完整的 J2EE 容器,它并不支持所有的 JSR-250 Annotations(其中@RolesAllowed之一)。此外,尽管 CXF 可以识别并使用@RolesAllowed,但它不捆绑实现,期望它由 J2EE 容器或包含的上述 api 提供。

之所以列出,servlet-api是因为我在编译时需要它来添加一个方法HellowWorld.java(见下文)。

二、修改beans.xml如下:

<bean class="my.pkg.HelloWorld" id="helloWorldService"/>

<jaxrs:serviceBeans>
   <ref bean="helloWorldService"/>
</jaxrs:serviceBeans>

<bean id="authorizationInterceptor"
      class="org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor">
  <property name="securedObject" ref="helloWorldService" />
</bean>

SecureAnnotationsInterceptor将扫描helloWorldService并强制执行@RolesAllowed注释。

请注意,helloWorldService必须从节中拉出,<jaxrs:serviceBeans>以便可以在此处和authorizationInterceptor.

第三,添加一些角色和用户tomcat-users.xml或替代(例如JDBC Realm等)我这样做了:

<role rolename="hello-user" />
<role rolename="hello-role1"/>
<role rolename="hello-role2" />
<user username="hello1" password="Password1" roles="hello-role1,hello-user"/>
<user username="hello2" password="Password1" roles="hello-role2,hello-user"/>

这将创建 2 个用户,每个用户都有一个共享角色 ( hello-user) 以及他们自己的不同角色。

第四,添加以下内容web.xml以启用BASIC身份验证:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Hello Services</web-resource-name>
        <url-pattern>/hello/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>hello-user</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>default</realm-name>
</login-config> 

有了这个,我决定hello-user/hello/*. 这不是必需的,但请注意,我确实遇到了一些问题,省略了一些节、通配符和角色......所以在这里小心试验。

第五(也是最后),标记HelloWorld.java类:

@Path("/hello")
@RolesAllowed("hello-user")
public class HelloWorld {

    @GET
    @Path("/echo/{input}")
    @Produces("text/plain")
    @RolesAllowed("hello-role1") 
    public String ping(@PathParam("input") String input) {
        return input;
    }

    @POST
    @Produces("application/json")
    @Consumes("application/json")
    @Path("/jsonBean")
    @RolesAllowed("hello-role2") 
    public Response modifyJson(JsonBean input) {
        input.setVal2(input.getVal1());
        return Response.ok().entity(input).build();
    }

    @GET
    @Produces("text/plain")
    @Path("/cliche")
    public Response getClichedMessage(@Context HttpServletRequest request) {
            return Response.
                    ok().
                    entity("Sending \"Hello World\" to user \"" + request.getUserPrincipal().getName() + "\"").
                    build();

    }    

}

我添加了最后一个方法 ( getClichedMessage()) 以表明两个用户都可以访问该方法,因为他们具有hello-user注释类的角色。SecureAnnotationsInterceptor足够聪明来处理这个问题。

就这样。在我看来,这是仅使用 Tomcat、CXF 和 BASIC authenitcation 的 STTCPW。CXF + 的关键@RolesAllowedSecureAnnotationsInterceptor.

更新:我应该承认将 Jersey REST 示例转换为 Apache CXF特别有帮助,特别是对于指出 SecureAnnotationsInterceptor 的连接在@RolesAllowed其他地方没有很好的记录。

更新 2:Jersey-CXF 博客条目似乎没有迁移到gmazza新博客。但是,我使用的示例在 github 上。它包含一个带有定义的配置文件SecureAnnotationsInterceptor和一个带有注释的bean@RolesAllowed

于 2013-07-18T19:36:14.250 回答