Protección de las aplicaciones de JAX-RS en el contenedor web

Puede utilizar la seguridad de servicios disponibles en el contenedor web para proteger los recursos REST (Representational State Transfer). Puede configurar mecanismos de seguridad que definen la autenticación de usuario, la seguridad de transporte, el control de autorización y las correlaciones de usuarios y roles.

Antes de empezar

Para definir restricciones de seguridad de forma correcta, es importante que esté familiarizado con la aplicación y los recursos RESTful que expone. Este conocimiento le ayudará a determinar los roles de seguridad apropiados que son necesarios para su aplicación así como los recursos individuales que expone.

Para ilustrar cómo proteger una aplicación REST, este tema utiliza un ejemplo de aplicación REST denominado AddressBookApp.

Debe completar la instalación de la aplicación en el servidor de aplicaciones. Por ejemplo, después de instalar la aplicación AddressBookApp, el descriptor de despliegue de AddressBookApp que se encuentra en el directorioraíz_perfil/config/cells/cellName/applications/applicationName.ear/deployments/applicationName_war/applicationName.war/WEB-INF es similar al del ejemplo siguiente:
<?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>
En este ejemplo, la correlación de servlet indica que los recursos REST reciben servicio bajo el directorio /contexto_raíz_aplic/rest donde contexto_raíz_aplic es lo que se ha configurado durante la instalación de la aplicación. El contexto raíz predeterminado es /.

Debe habilitar la seguridad para WebSphere Application Server.

Acerca de esta tarea

Puede utilizar el contenedor web para aplicar la autenticación así como restricciones de autorización para una aplicación REST que se ejecute en el entorno del servidor de aplicaciones. La autenticación es un requisito básico de seguridad para recursos REST empresariales que requieren un nivel mínimo de seguridad y es posible que necesite proteger más los recursos basados en la identidad del interlocutor.

Puede configurar los siguientes mecanismos de seguridad para recursos REST:
  • Solicitar que los usuarios se autentique en la aplicación utilizando la autenticación básica HTTP o un formulario de inicio de sesión.
  • Configurar la aplicación para utilizar un canal SSL para el transporte cuando se invocan recursos REST.
  • Definir restricciones de autorización basados en roles en sus patrones de recursos REST.
  • Implementar el uso programático del objeto SecurityContext anotado para determinar la identidad de usuario y roles.

Procedimiento

  1. Asegúrese de que se ha habilitado la seguridad para el servidor de aplicaciones.
    1. Inicie la consola administrativa de WebSphere Application Server.

      Inicie el gestor de despliegue y en el intermediario escriba la dirección de su servidor WebSphere Application Server, Network Deployment. De forma predeterminada, la consola se encuentra en http://su_sistema_host.su_dominio:9060/ibm/console.

      Si la seguridad está inhabilitada actualmente, se le solicita que especifique un ID de usuario. Inicie la sesión con cualquier ID de usuario. Sin embargo, si la seguridad está habilitada actualmente, se le solicita que especifique un ID de usuario y una contraseña. Inicie la sesión con un ID de usuario y una contraseña de administrador predefinidos.

    2. Pulse Seguridad > Seguridad global.

      Seleccione Habilitar seguridad de aplicaciones.

      Avoid trouble Avoid trouble: Debe habilitar la seguridad administrativa. Solamente puede tener habilitada la seguridad de aplicaciones cuando se ha habilitado la seguridad administrativa. gotcha
  2. Añada restricciones de seguridad.
    Edite el archivo web.xml de la aplicación o utilice una herramienta de ensamblaje para añadir restricciones de seguridad a su aplicación. El fragmento de código siguiente es una restricción de seguridad aplicada a la aplicación de ejemplo AddressBookApp:
    <!-- Limitación de seguridad para el ejemplo de aplicación -->
      <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>

    En este ejemplo, existe un recurso web que se encuentra en /raíz_contexto/rest/direcciones que puede responder a una solicitud HTTP GET o POST. Una restricción de seguridad, AuthConstraint_1, se aplica al recurso web. La restricción de autorización especifica que el rol Role1 es necesario para que los usuarios puedan acceder al recurso.

  3. Elija uno o varios de los mecanismos de seguridad siguientes para configurar su aplicación REST.
    • Habilitar la autenticación HTTP.
      1. Añada restricciones de seguridad editando el archivo web.xml tal como se describió anteriormente.
      2. Configure el archivo web.xml para la aplicación HTTP básica.
        Edite el archivo web.xml para la aplicación y añada el elemento siguiente para especificar el uso de la autenticación HTTP básica. De forma predeterminada, el entorno de ejecución de seguridad del servidor de aplicaciones utiliza este método de autenticación.
        <!-- Esto define una configuración de inicio de sesión de autenticación básica HTTP. -->
         <login-config>
                <auth-method>BASIC</auth-method>
                <realm-name>test realm</realm-name>
         </login-config>
        Ahora se habrá definido un método de autentiacación HTTP básico. A los usuarios que intentan acceder al recurso se les solicitan las credenciales al inicio de sesión.
    • Habilitar el inicio de sesión de formulario.
      1. Añada restricciones de seguridad editando el archivo web.xml tal como se describió anteriormente.
      2. Edite el archivo web.xml para la aplicación y añada el elemento siguiente para especificar el uso del inicio de sesión de formulario:
        <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>
        Es importante que se sustituyan los valores de página web logon.jsp y logonError.jsp por el inicio de sesión de formulario y el proceso de errores, respectivamente. Cuando se acceda a la aplicación, los usuarios se redirigirán a través de la página web logon.jsp para su autenticación. Si se produce un error de autenticación, los usuarios se redirigirán a la página web logonError.jsp. En el ejemplo siguiente se muestra la ubicación de las páginas logon.jsp y logonError.jsp en la aplicación web del archivo archivador 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
        El fragmento de código siguiente muestra un formulario de inicio de sesión de ejemplo:
        <html>
        <head>
            <title>Página de inicio de sesión</title>
        </head>
        <h2>Hola, inicie la sesión:</h2>
        <br><br>
        <form action="j_security_check" method=post>
            <p><strong>Indique su nombre de usuario:</strong>
            <input type="text" name="j_username" size="25">
            <p><p><strong>Indique su contraseña: </strong>
            <input type="password" size="15" name="j_password">
            <p><p>
            <input type="submit" value="Submit">
            <input type="reset" value="Reset">
        </form>
        </html>
    • Habilitar SSL para la aplicación.
      1. Añada restricciones de seguridad editando el archivo web.xml tal como se describió anteriormente.
      2. Edite el archivo web.xml para la aplicación y añada el siguiente elemento en el elemento de restricción de seguridad:
        <user-data-constraint id="UserDataConstraint_1">
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
         </user-data-constraint>
        Si no desea utilizar SSL, puede saltarse esta restricción o sustituir el valor CONFIDENTIAL por NONE.
    • Habilitar el control de autorización para proteger los recursos utilizando patrones URL.
      1. Añada restricciones de seguridad editando el archivo web.xml tal como se describió anteriormente.
      2. Edite el archivo web.xml para la aplicación y añada el siguiente elemento en el elemento de restricción de seguridad. En el ejemplo siguiente, Role1 y Role2 especifican que se protejan los recursos REST, /rest/addresses y /rest/resources/{i}, respectivamente:
        <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>

        En este ejemplo, sólo los usuarios que sean miembros de Role1 pueden acceder a root-context/rest/addresses y sólo los usuarios que sean miembros de Role2 pueden acceder al recurso root-context/rest/addresses/{i}.

        Avoid trouble Avoid trouble: Es importante que como prefijo de la vía de los recursos protegidos utilice la correlación de servlet en las restricciones de seguridad que defina. Para evitar saltarse alguna comprobación de acceso, puede optar por correlacionar el servlet con la vía de acceso /*. Esta correlación protege todos los recursos bajo el contexto raíz.gotcha
        Asegúrese de definir los roles insertando elementos de definición de roles dentro del elemento <web-app>; por ejemplo:
        <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>  

        Los cambios que realice en el descriptor de despliegue son recogidos automáticamente por el entorno de ejecución del servidor de aplicaciones y no es necesario reiniciar la aplicación o el servidor. Otros tipos de cambios, como el del URL de correlación, requieren que se reinicie el servidor de aplicaciones. Se recomienda que reiniciar la aplicación para asegurarse de que los cambios entren en vigor.

    • Utilización de forma programática del contexto de seguridad anotado.
      Los desarrolladores de aplicaciones pueden utilizar la anotación JAX-RS @SecurityContext para ver en cascada de forma programática el contexto de seguridad en el recurso de la parte del servidor y habilitar la definición de atributos de seguridad durante el tiempo de ejecución. A continuación se muestra la funcionalidad que proporciona la interfaz SecurityContext:
      public String getAuthenticationScheme()
      public Principal getUserPrincipal()
      public boolean isUserInRole(String role)
      En el ejemplo siguiente se ilustra la interfaz 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();
          }
      }
    • Utilizar el manejador de clientes de seguridad para llevar a cabo la autenticación HTTP básica
      También puede utilizar el manejador de clientes de seguridad para llevar a cabo la autenticación HTTP básica con un recurso JAX-RS seguro. En el ejemplo siguiente se muestra el modelo de programación simple para realizar esta tarea:
      /**
       * 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.
      Cuando se utiliza la clase BasicAuthSecurityHandler, asegúrese de que se dirige a los recursos de destino utilizando el esquema https para sus URL y que la aplicación de destino está habilitada para SSL. Se recomienda encarecidamente que utilice conexiones SSL al enviar credenciales de usuario. Explícitamente puede desactivar el requisito para SSL en la clase BasicAuthSecurityHandler invocando el método setSSLRequired en el manejador de seguridad con el valor false . De forma predeterminada, este valor es true.
      secHandler.setSSLRequired(false);
      Opcionalmente, también puede proporcionar las credenciales de usuario en la línea de mandatos Java™ de su cliente de la manera siguiente:
      java -Duser=test_user -Dpassword=your_password  your_client_program
      Si lo desea, puede recuperar las credenciales del usuario de un archivo de propiedades cuya ubicación se especifica en la línea de mandatos Java de la manera siguiente:
      java -Dclientpropsdir=directorio_archivo_propiedades  programa_cliente
      donde directorio_archivo_propiedades contiene el archivo wink.client.props en el que se establecen las propiedades user y password.

Resultados

Después de definir restricciones de seguridad, el acceso a los recursos REST que están definidos en la aplicación estará sujeto solamente a la autenticación de usuario correcta. Además, habrá aplicado restricciones de roles en varios patrones de URL de recursos para permitir el acceso basado en roles a esos recursos.

Ejemplo

En el ejemplo siguiente se muestra el descriptor de despliegue web.xml para la aplicación AddressBookApp donde se han definido restricciones de seguridad utilizando los pasos del procedimiento anterior:
<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>

Qué hacer a continuación

Utilice la consola de administración para administrar la seguridad en su aplicación de JAX-RS.


Icon that indicates the type of topic Task topic



Timestamp icon Last updated: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_jaxrs_impl_securejaxrs_webcont
File name: twbs_jaxrs_impl_securejaxrs_webcont.html