Protegendo Aplicativos JAX-RS Dentro do Contêiner da Web

É possível usar serviços de segurança disponíveis a partir do contêiner da Web para proteger recursos Representational State Transfer (REST). É possível configurar os mecanismos de segurança que definem o aplicativo do usuário, a segurança de transporte, o controle de autorização e o usuário para mapeamentos de função.

Antes de Iniciar

Para definir apropriadamente as restrições de segurança, é importante estar familiarizado com seu aplicativo e com os recursos RESTful que ele expõe. Esse conhecimento ajuda a determinar as funções de segurança apropriadas necessárias pelo seu aplicativo, além de recursos individuais que ele expõe.

Para mostrar como proteger um aplicativo REST, este tópico usa um aplicativo REST de amostra denominado AddressBookApp.

É necessário concluir a instalação do seu aplicativo no servidor de aplicativos. Por exemplo, depois de instalar o aplicativo AddressBookApp, o descritor de implementação AddressBookApp localizado no diretório profile_root/config/cells/cellName/applications/applicationName.ear/deployments/applicationName_war/applicationName.war/WEB-INF é semelhante ao seguinte exemplo:
<?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>
Nesse exemplo, o mapeamento de servlet indica que os recursos REST são atendidos no diretório /app_root_context/rest, em que app_root_context é o que você configurou durante a instalação do aplicativo. O contexto raiz padrão é /.

Você deve ativar a segurança para o WebSphere Application Server.

Sobre Esta Tarefa

É possível usar o contêiner da Web para aplicar autenticação assim como restrições de autorização a um aplicativo REST que esteja executando no ambiente do servidor de aplicativos. A autenticação é um requisito de segurança básico para os recursos REST de negócios que requerem nível mínimo de segurança e podem precisar proteger ainda mais os recursos com base na identidade do responsável pela chamada.

É possível configurar os seguintes mecanismos de segurança para os recursos REST:
  • Requer que os usuários sejam autenticados no seu aplicativo usando autenticação básica HTTP ou login de formulário.
  • Configure seu aplicativo para usar um canal SSL para transporte quando chamar recursos REST.
  • Defina restrições de autorização com base em função nos padrões de recurso REST.
  • Implemente o uso programático do objeto SecurityContext anotado para determinar a identidade e as funções de usuário.

Procedimento

  1. Certifique-se de que a segurança esteja ativada para o servidor de aplicativos.
    1. Inicie o console administrativo do WebSphere Application Server.

      Inicie o gerenciador de implementação e, no seu navegador, digite o endereço do seu servidor WebSphere Application Server, Network Deployment. Por padrão, o console está localizado em http://your_host.your_domain:9060/ibm/console.

      Se a segurança estiver atualmente desativada, será solicitado um ID do usuário. Efetue login com qualquer ID do usuário. Entretanto, se a segurança estiver atualmente ativada, será solicitado um ID do usuário e uma senha. Efetue login com um ID do usuário administrativo e senha predefinidos.

    2. Clique em Segurança > Segurança Global.

      Selecione Ativar segurança do aplicativo.

      Evitar Problemas Evitar Problemas: É necessário ativar a segurança administrativa. A segurança do aplicativo é ativada apenas quando a segurança administrativa estiver ativada. gotcha
  2. Inclua restrições de segurança.
    Edite o arquivo web.xml para o aplicativo ou use uma ferramenta de montagem para incluir restrições de segurança no aplicativo. O seguinte fragmento de código é uma restrição de segurança aplicada ao aplicativo de amostra 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>

    Nesse exemplo, existe um recurso da Web localizado em /root_context/rest/addresses que pode responder a um pedido HTTP GET ou POST. Uma restrição de segurança, AuthConstraint_1, é aplicada ao recurso da Web. A restrição de autorização especifica a função Role1 necessária para os usuários acessarem o recurso.

  3. Escolha um ou mais dos seguintes mecanismos de segurança para configurar seu aplicativo REST.
    • Ative a autenticação básica HTTP.
      1. Inclua restrições de segurança ao editar o arquivo web.xml conforme descrito anteriormente.
      2. Configure o arquivo web.xml para ativar a autenticação básica HTTP.
        Edite o arquivo web.xml para o aplicativo e inclua o seguinte elemento para especificar o uso da autenticação básica HTTP. Por padrão, o ambiente de tempo de execução de segurança do servidor usa esse método de autenticação.
        <!-- This defines a HTTP basic authentication login configuration. -->
         <login-config>
                <auth-method>BASIC</auth-method>
                <realm-name>test realm</realm-name>
         </login-config>
        Um método de autenticação básica HTTP está agora definido. Os usuários que tentarem acessar o recurso precisam efetuar login com credenciais.
    • Ative o login de formulário.
      1. Inclua restrições de segurança ao editar o arquivo web.xml conforme descrito anteriormente.
      2. Edite o arquivo web.xml para o aplicativo e inclua o seguinte elemento para especificar o uso do login de formulário.
        <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>
        É importante substituir os valores de página da Web logon.jsp e logonError.jsp pelo seu login de formulário e processamento de erro, respectivamente. Ao acessar o aplicativo, os usuários são redirecionados por meio da página da Web logon.jsp para autenticação. Se houver uma falha de autenticação, os usuários são redirecionados para a página da Web logonError.jsp. O exemplo a seguir ilustra o posicionamento das páginas logon.jsp e logonError.jsp no arquivo web application archive (WAR) do aplicativo:
        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
        O seguinte fragmento de código mostra um formulário de logon de amostra:
        <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>
    • Ative o SSL para seu aplicativo.
      1. Inclua restrições de segurança ao editar o arquivo web.xml conforme descrito anteriormente.
      2. Edite o arquivo web.xml para o aplicativo e inclua o seguinte elemento dentro do elemento de restrição de segurança.
        <user-data-constraint id="UserDataConstraint_1">
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
         </user-data-constraint>
        Se não desejar usar SSL, será possível ignorar esta restrição ou substituir o valor CONFIDENTIAL por NONE.
    • Ative o controle de autorização para proteger recursos usando padrões de URL.
      1. Inclua restrições de segurança ao editar o arquivo web.xml conforme descrito anteriormente.
      2. Edite o arquivo web.xml para o aplicativo e inclua o seguinte elemento dentro do elemento de restrição de segurança. No seguinte exemplo, Role1 e Role2 especificam para proteger os recursos REST, /rest/addresses e /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>

        Nesse exemplo, apenas os usuários que são membros de Role1 podem acessar root-context/rest/addresses e apenas os usuários que são membros de Role2 podem acessar o recurso,root-context/rest/addresses/{i}.

        Evitar Problemas Evitar Problemas: É importante prefixar o caminho dos recursos protegidos com seu mapeamento de servlet nas restrições de segurança definidas. Para impedir o desvio de quaisquer verificações de acesso, poderá escolher mapear o servlet para o caminho /*. Esse mapeamento protege todos os recursos no contexto raiz.gotcha
        Certifique-se de definir suas funções ao inserir os elementos de definição de função no elemento <web-app>, como por exemplo:
        <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>  

        As mudanças feitas no descritor de implementação são automaticamente selecionadas pelo ambiente de tempo de execução do servidor de aplicativos e não é necessário reiniciar o aplicativo ou o servidor. Outros tipos de mudanças, como URL de mapeamento, requerem reiniciar o servidor de aplicativos. É recomendado reiniciar o aplicativo para certificar-se de que suas mudanças tomem efeito.

    • Usando programaticamente o contexto de segurança anotado.
      Os desenvolvedores de aplicativos podem usar a anotação JAX-RS @SecurityContext para distribuir programaticamente em cascata o contexto de segurança para o recurso no lado do servidor e ativar a definição dos atributos de segurança durante o tempo de execução. A seguir há a funcionalidade fornecida pela interface SecurityContext:
      public String getAuthenticationScheme()
      public Principal getUserPrincipal()
      public boolean isUserInRole(String role)
      O seguinte exemplo mostra a interface 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;
      
      /**   
       * Um recurso de amostra que fornece acesso a uma lista de endereços. 
       * 
       */
      @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() {
             // recupere o esquema de autenticação que foi usado(ex.: BÁSICO)
             String authnScheme = securityContext.getAuthenticationScheme());
             // recupere o nome do Principal que invocou o recurso
             String username = securityContext.getUserPrincipal().getName());
             // verifique se o usuário atual está na Função1 
              isUserInRole booleano = securityContext.isUserInRole(“Função1”);
          	 
              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();
          }
      }
    • Use o manipulador do cliente de segurança para executar autenticação básica HTTP
      É possível usar opcionalmente o manipulador do cliente de segurança para executar autenticação básica HTTP com um recurso JAX-RS protegido. O seguinte exemplo mostra um modelo de programação simples para executar essa tarefa:
      /**
       * Este fragmento ilustra o uso do JAX-RS SecurityHandler por um
       * cliente para executar a autenticação básica de HTTP com um serviço de destino.
       */ 
       
       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();
      
       // Configure a credencial do usuário.
       secHandler.setUsername("user1");
       secHandler.setPassword("security");
      
       // Inclua este manipulador de segurança na cadeia de manipuladores.
       config.handlers(secHandler);
      
       // Crie a instância do cliente REST. 
       RestClient client = new RestClient(config);
      
       // Crie a instância do recurso para interagir com o 
       // substituta para seu endereço do recurso
       resource =  
        client.resource("http://localhost:8080/path/to/resource");
      
      // Now you are ready to call your resource.
      Ao usar a classe BasicAuthSecurityHandler, certifique-se de ter marcado os recursos como destino usando o esquema https para as suas URLs, e que o aplicativo de destino está ativado para SSL. É altamente recomendado usar conexões SSL ao enviar credenciais de usuário. Você pode explicitamente desativar o requisito para SSL na classe BasicAuthSecurityHandler chamando o método setSSLRequired no manipulador de segurança com o valor false. Por padrão, esse valor é verdadeiro.
      secHandler.setSSLRequired(false);
      Opcionalmente, também é possível fornecer as credenciais do usuário na linha de comandos Java™ para seu cliente da seguinte forma:
      java -Duser=test_user -Dpassword=your_password  your_client_program
      É possível opcionalmente recuperar as credenciais do usuário a partir de arquivos de propriedades cujo local você especifica na linha de comandos Java da seguinte forma:
      java -Dclientpropsdir=directory_for_your_properties_file  your_client_program
      em que directory_for_your_properties_file contém o arquivo wink.client.props onde as propriedades user e password são configuradas.

Resultados

Depois de definir as restrições de segurança, o acesso aos recursos REST que são definidos no seu aplicativo está sujeito apenas para autenticação do usuário com êxito. Além disso, você aplicou as restrições de função em vários padrões de URL de recurso para ativar o acesso baseado em função para esses recursos.

Exemplo

O seguinte exemplo mostra o descritor de implementação web.xml para o aplicativo de amostra AddressBookApp onde as restrições de segurança foram definidas usando as etapas de procedimento anteriores:
<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>

O que Fazer Depois

Use o console administrativo para administrar a segurança para seu aplicativo JAX-RS.


Ícone que indica o tipo de tópico Tópico de Tarefa



Ícone de registro de data e hora Última atualização: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_jaxrs_impl_securejaxrs_webcont
Nome do arquivo: twbs_jaxrs_impl_securejaxrs_webcont.html