保护 Web 容器内的 JAX-RS 应用程序

您可以使用 Web 容器提供的安全服务来保护表示状态传输 (REST) 资源。 您可以配置安全性机制,其定义用户认证、传输安全、权限控制以及用户到角色的映射。

开始之前

为了相应定义安全性约束,重要的是,您熟悉应用程序及其展示的 RESTful 资源。此知识帮助您确定您应用程序所需的相应安全角色及其展示的单个资源。

为了说明如何保护 REST 应用程序,本主题使用称为 AddressBookApp 的样本 REST 应用程序。

您必须在应用程序服务器上完成应用程序的安装。例如,在您安装 AddressBookApp 应用程序之后,在 profile_root/config/cells/cellName/applications/applicationName.ear/deployments/applicationName_war/applicationName.war/WEB-INF 目录中找到的 AddressBookApp 部署描述符如以下示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_1255468655347">
 <display-name>Sample REST Web Application</display-name>
  <servlet>
    <servlet-name>AddressBookApp</servlet-name>
    <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>com.test.AddressBookApplication</param-value>
</init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>AddressBookApp</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>
在此示例中,servlet 映射指示在 /app_root_context/rest 目录(其中,app_root_context 是您在应用程序安装期间配置的)下提供 REST 资源。缺省根上下文是 /

您必须为 WebSphere Application Server 启用安全性。

关于此任务

您可以使用 Web 容器来应用认证以及将授权约束应用于在应用程序服务器环境中运行的 REST 应用程序。认证是需要最低安全性级别的业务 REST 资源的基本安全要求,可能需要基于调用者的身份进一步保护资源。

您可以为 REST 资源配置以下安全性机制:
  • 要求用户使用 HTTP 基本认证或表单登录向应用程序进行认证。
  • 配置应用程序以在调用 REST 资源时将 SSL 通道用于传输。
  • 定义对 REST 资源模式的基于角色的授权约束。
  • 实施注解的 SecurityContext 对象的编程使用以确定用户身份和角色。

过程

  1. 确保为应用程序服务器启用安全性。
    1. 启动 WebSphere Application Server 管理控制台。

      启动 Deployment Manager,在浏览器中输入 WebSphere Application Server Network Deployment 服务器的地址。缺省情况下,控制台的位置是 http://your_host.your_domain:9060/ibm/console

      如果当前已禁用安全性,那么将提示您输入用户标识。请使用任何用户标识登录。但是,如果当前已启用安全性,那么将提示您输入用户标识和密码。请使用预定义的管理用户标识和密码登录。

    2. 单击安全性 > 全局安全性

      选择启用应用程序安全性

      避免故障 避免故障: 您必须启用管理安全性。您只能在启用管理安全性时,启用应用程序安全性。gotcha
  2. 添加安全性约束。
    为应用程序编辑 web.xml 文件,或者使用组装工具向应用程序添加安全性约束。以下代码片段是应用于 AddressBookApp 样本应用程序的安全性约束:
    <!-- Security constraint for the sample application -->
      <security-constraint id="SecurityConstraint_1">
        <!-- This defines the REST resource associated with the constraint. -->
        <web-resource-collection id="WebResourceCollection_1">
          <web-resource-name>AddressBookApp</web-resource-name>
          <description>Protection area for Rest resource /addresses </description>
          <url-pattern>/rest/addresses</url-pattern>
          <http-method>GET</http-method>
          <http-method>POST</http-method>
        </web-resource-collection>
    
        <!—This defines an authorization constraint by requiring Role1 for the resource. -->
        <auth-constraint id="AuthConstraint_1">
          <description>Used to guard resources under this url-pattern </description>
          <role-name>Role1</role-name>
        </auth-constraint>
      </security-constraint>

    在此示例中,位于 /root_context/rest/addresses 的 Web 资源可以对应于 HTTP GET 或 POST 请求。安全性约束 AuthConstraint_1 应用于 Web 资源。授权约束指定需要角色 Role1 才能让用户访问资源。

  3. 选择要为 REST 应用程序配置的一个或多个以下安全性机制。
    • 启用基本 HTTP 认证。
      1. 通过如先前所述地编辑 web.xml 文件来添加安全性约束。
      2. 配置 web.xml 文件以启用基本 HTTP 认证。
        编辑应用程序的 web.xml 文件,然后添加以下元素来指定基本 HTTP 认证的用法。缺省情况下,应用程序服务器安全运行时环境使用此认证方法。
        <!-- This defines a HTTP basic authentication login configuration. -->
         <login-config>
                <auth-method>BASIC</auth-method>
                <realm-name>test realm</realm-name>
         </login-config>
        现在,已定义 HTTP 基本认证方法。尝试访问资源的用户需要使用凭证来登录。
    • 启用表单登录。
      1. 通过如先前所述地编辑 web.xml 文件来添加安全性约束。
      2. 编辑应用程序的 web.xml 文件,然后添加以下元素来指定表单登录的用法:
        <login-config>
              <auth-method>FORM</auth-method>
              <form-login-config>
                 <form-login-page>/logon.jsp</form-login-page>
                 <form-error-page>/logonError.jsp</form-error-page>
              </form-login-config>
        </login-config>
        重要的是,您将 logon.jsp 和 logonError.jsp Web 页面值分别替换为表单登录和错误处理。访问应用程序时,通过 logon.jsp Web 页面将用户重定向来认证。 如果认证失败,将用户重定向到 logonError.jsp Web 页面。以下示例说明 logon.jsp 和 logonError.jsp 页面在 Web 应用程序归档 (WAR) 文件中的放置:
        META-INF    
              logon.jsp
              logonError.jsp
              WEB-INF/classes/
              WEB-INF/classes/
              WEB-INF/classes/com/
              WEB-INF/classes/com/test/   
              WEB- NF/classes/com/test/AddressBookApplication.class
              WEB-INF/classes/com/test/AddressBookResource.class
        以下代码片段说明样本登录表单:
        <html>
        <head>
            <title>Login Page</title>
        </head>
        <h2>Hello, please log in:</h2>
        <br><br>
        <form action="j_security_check" method=post>
            <p><strong>Please Enter Your User Name: </strong>
            <input type="text" name="j_username" size="25">
            <p><p><strong>Please Enter Your Password: </strong>
            <input type="password" size="15" name="j_password">
            <p><p>
            <input type="submit" value="Submit">
            <input type="reset" value="Reset">
        </form>
        </html>
    • 为应用程序启用 SSL。
      1. 通过如先前所述地编辑 web.xml 文件来添加安全性约束。
      2. 编辑应用程序的 web.xml 文件,然后在安全性约束元素内添加以下元素:
        <user-data-constraint id="UserDataConstraint_1">
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
         </user-data-constraint>
        如果您希望使用 SSL,可以跳过此约束或者将 CONFIDENTIAL 值替换为 NONE
    • 启用授权控制以使用 URL 模式保护资源。
      1. 通过如先前所述地编辑 web.xml 文件来添加安全性约束。
      2. 编辑应用程序的 web.xml 文件,然后在安全性约束元素内添加以下元素。在以下示例中,Role1Role2 指定来分别保护 REST 资源 /rest/addresses/rest/resources/{i}
        <security-constraint id="SecurityConstraint_1">
            <web-resource-collection id="WebResourceCollection_1">
              <web-resource-name>AddressBookApp</web-resource-name>
              <description>Protection area for Rest Servlet</description>
              <url-pattern>/rest/addresses</url-pattern>
              <http-method>GET</http-method>
              <http-method>POST</http-method>
            </web-resource-collection>
            <auth-constraint id="AuthConstraint_1">
                 <description> Role1 for this rest resource </description>
                 <role-name>Role1</role-name>
              </auth-constraint> 
        </security-constraint>
        
        <security-constraint id="SecurityConstraint_2">
            <web-resource-collection id="WebResourceCollection_2">
              <web-resource-name>AddressBookApp</web-resource-name>
              <description>Protection area for Rest Servlet</description>
              <url-pattern>/rest/addresses/*</url-pattern>
              <http-method>GET</http-method>
              <http-method>POST</http-method>
            </web-resource-collection>
            <auth-constraint id="AuthConstraint_2">
                 <description> Role2 for this rest resource </description>
                 <role-name>Role2</role-name>
              </auth-constraint>
        </security-constraint>

        在此示例中,只有作为 Role1 的成员的用户可以访问 root-context/rest/addresses 而只有作为 Role2 的成员的用户才可以访问资源 root-context/rest/addresses/{i}

        避免故障 避免故障: 重要的是,使用安全性约束中您定义的 servlet 映射在受保护资源的路径前面加上前缀。为了防止绕过任何访问检查,您可以选择将 servlet 映射到 /* 路径。该映射保护根上下文下的所有资源。gotcha
        确保通过将角色定义元素插入 <web-app> 元素内来定义您的角色;例如:
        <security-role id="SecurityRole_1">
            <description>This is Role1</description>
            <role-name>Role1</role-name>
        </security-role>  
        <security-role id="SecurityRole_2">
            <description>This is Role2</description>
            <role-name>Role2</role-name>
        </security-role>  

        您对部署描述符的更改自动由应用程序服务器运行时环境拾取,而您无需重新启动应用程序或服务器。其他类型的更改(例如,映射 URL)需要您重新启动应用程序服务器。建议您重新启动应用程序以确保您的更改生效。

    • 以编程方式使用注解安全上下文。
      应用程序开发者可以使用 JAX-RS @SecurityContext 注解以编程方式将安全上下文向下层叠到服务器端上的资源,并在运行时中启用安全属性的定义。 以下是 SecurityContext 接口提供的功能:
      public String getAuthenticationScheme()
      public Principal getUserPrincipal()
      public boolean isUserInRole(String role)
      以下示例说明 SecurityContext 接口:
      package com.test;
      
      import javax.ws.rs.GET; 
      import javax.ws.rs.Consumes;
      import javax.ws.rs.POST;
      import javax.ws.rs.Path;
      import javax.ws.rs.PathParam;
      import javax.ws.rs.Produces;
      import javax.ws.rs.ext.*;
      import javax.ws.rs.core.SecurityContext;
      import javax.ws.rs.core.Context;
      
      /**   
       * A sample resource that provides access to an address book. 
       * 
       */
      @Path(value="/addresses")
      public class AddressBookResource {
      	
      	@Context private SecurityContext securityContext;
          
          private static String[] list = new String[] {
              "Michael",
              "Ron",
              "Jane",
              "Sam"
          };
          
          @GET
          @Produces(value="text/plain")
          public String getList() {
             // retrieve the authentication scheme that was used(e.g. BASIC)
             String authnScheme = securityContext.getAuthenticationScheme());
             // retrieve the name of the Principal that invoked the resource
             String username = securityContext.getUserPrincipal().getName());
             // check if the current user is in Role1 
              Boolean isUserInRole = securityContext.isUserInRole(“Role1”);
          	 
              StringBuffer buffer = new StringBuffer();
              buffer.append("{");
              for (int i = 0; i < list.length; ++i) {
                  if (i != 0) 
                      buffer.append(", ");
                  buffer.append(list[i]);
              }
              buffer.append("}");
              
              return buffer.toString();
          }
      }
    • 使用安全客户机处理程序来执行基本 HTTP 认证
      (可选)您可以使用安全客户机处理程序对安全 JAX-RS 资源执行基本 HTTP 认证。以下示例说明用于完成此任务的简单编程模型:
      /**
       * This snippet illustrates the use of the JAX-RS SecurityHandler by a
       * client to perform HTTP basic authentication with a target service.
       */ 
       
       import org.apache.wink.client.ClientConfig;
       import org.apache.wink.client.Resource;
       import org.apache.wink.client.RestClient;
       import org.apache.wink.client.handlers.BasicAuthSecurityHandler;
      
       ClientConfig config = new ClientConfig();
        BasicAuthSecurityHandler secHandler = new    
       BasicAuthSecurityHandler();
      
       // Set the user credential.
       secHandler.setUsername("user1");
       secHandler.setPassword("security");
      
       // Add this security handler to the handlers chain.
       config.handlers(secHandler);
      
       // Create the REST client instance. 
       RestClient client = new RestClient(config);
      
       // Create the resource instance to interact with 
       // substitute for your resource address
       resource =  
        client.resource("http://localhost:8080/path/to/resource");
      
      // Now you are ready to call your resource.
      使用 BasicAuthSecurityHandler 类时,确保您瞄准使用 URL 的 https 方案的资源,且目标应用程序支持 SSL。极力建议您在发送用户凭证时使用 SSL 连接。您可能通过以 false 值在安全处理程序上调用 setSSLRequired 方法在 LtpaAuthSecurityHandler 类中显式关闭对 SSL 的需求。缺省情况下,该值为 true
      secHandler.setSSLRequired(false);
      (可选)您还可以在 Java™ 命令行上为您的客户机提供用户凭证,如下所示:
      java -Duser=test_user -Dpassword=your_password  your_client_program
      (可选)您可以从属性文件检索用户凭证,您在 Java 命令行上指定该文件位置,如下所示:
      java -Dclientpropsdir=directory_for_your_properties_file  your_client_program
      其中 directory_for_your_properties_file 包含 wink.client.props 文件,在该文件中设置了 userpassword 属性。

结果

在您定义安全性约束之后,对应用程序中定义的 REST 资源的访问只取决于用户认证是否成功。此外,您将角色约束应用于各种资源 URL 模式以启用对这些资源的基于角色访问。

示例

以下示例说明 AddressBookApp 样本应用程序的 web.xml 部署描述符,其中使用先前的过程步骤定义了安全性约束。
<web-app id="WebApp_1255468655347">
    <display-name>Sample REST Web Application</display-name>
    <servlet>
        <servlet-name>AddressBookApp</servlet-name>
        <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.test.AddressBookApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AddressBookApp</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <security-constraint id="SecurityConstraint_1">
      <web-resource-collection id="WebResourceCollection_1">
        <web-resource-name>AddressBookApp</web-resource-name>
        <description>Protection area for Rest Servlet</description>
        <url-pattern>/rest/addresses</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint id="AuthConstraint_1">
         <description>Role1 for this rest servlet</description>
         <role-name>Role1</role-name>
      </auth-constraint> 
      <user-data-constraint id="UserDataConstraint_1">
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
    </security-constraint>
    <security-constraint id="SecurityConstraint_2">
      <web-resource-collection id="WebResourceCollection_2">
        <web-resource-name>AddressBookApp</web-resource-name>
        <description>Protection area for Rest Servlet</description>
        <url-pattern>/rest/addresses/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint id="AuthConstraint_2">
         <description>Role2 for this rest servlet</description>
         <role-name>Role2</role-name>
      </auth-constraint> 
      <user-data-constraint id="UserDataConstraint_1">
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
    </security-constraint>
    <security-role id="SecurityRole_1">
         <description>This is Role1</description>
         <role-name>Role1</role-name>
    </security-role>  
    <security-role id="SecurityRole_2">
         <description>This is Role2</description>
         <role-name>Role2</role-name>
    </security-role>  
    <login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
         <form-login-page>/logon.jsp</form-login-page>
         <form-error-page>/logonError.jsp</form-error-page>
      </form-login-config>
    </login-config>
</web-app>

下一步做什么

使用管理控制台来管理 JAX-RS 应用程序的安全性。


指示主题类型的图标 任务主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_jaxrs_impl_securejaxrs_webcont
文件名:twbs_jaxrs_impl_securejaxrs_webcont.html