JavaServer Pages e Servlets possuem vários mecanismos disponíveis para desenvolvedores web protegerem seus aplicativos. Resources são seguros declarativamente por meio de verificações no descritor de implantação de aplicativos e atribuindo um papel a eles.

Vários níveis de recursos estão disponíveis, que vão desde a autenticação básica usando login e senha para autenticação sofisticada usando certificados.

Autenticação baseada na Role (Role Based Authentication):

O mecanismo de certificação da especificação Servlet usa um mecanismo chamado segurança baseada em funções(Role Based Authentication). Essa idéia é que ao invés de limitar os recursos a nível de usuário, criamos papéis e restringimos os recursos dos papéis.

Nós podemos definir diferentes papéis no arquivo de tomcat-users.xml, que é colocado no diretório home do Tomcat em conf. Segue abaixo um exemplo:

Listagem 1: Definindo diferentes papéis

<?xml version='1.0' encoding='utf-8'?> 
<tomcat-users> 
<role rolename="tomcat"/> 
<role rolename="role1"/> 
<role rolename="manager"/> 
<role rolename="admin"/> 
<user username="tomcat" password="tomcat" roles="tomcat"/> 
<user username="role1" password="tomcat" roles="role1"/> 
<user username="both" password="tomcat" roles="tomcat,manager"/> 
<user username="admin" password="secret" roles="admin,role1"/> 
</tomcat-users>

Este arquivo define um mapeamento entre o nome de usuário, senha e papel. A preocupação de que um determinado usuário pode ter mais de uma função, por exemplo, nome de usuário = "fulano" está no papel "tomcat" e a função "role1".

Uma vez identificados e definidos diferentes papéis, limitações de segurança podem ser colocados em diferentes recursos de aplicativos da Web usando o elemento no arquivo web.xml presente no diretório WEB-INF.

Listagem 2: exemplo de entrada web.xml

<web-app> 
... 
 <security-constraint> 
 <web-resource-collection> 
 <web-resource-name> 
 SecuredBookSite 
 </web-resource-name> 
<url-pattern>/secure</url-pattern> 
<http-method>POST</http-method> 
<http-method>GET</http-method> 
</web-resource-collection> 
 <auth-constraint> 
<description> 
Only admin can  use this app 
</description> 
 <role-name>admin</role-name> 
 </auth-constraint> 
</security-constraint> 
  <security-role> 
<role-name>role1r</role-name> 
 </security-role> 
 <login-config> 
 <auth-method>BASIC</auth-method> 
 </login-config> 
... 
</web-app>

O código acima quer dizer que:

  • Qualquer solicitação HTTP GET ou POST para um URL marcada por /secured/* estão sujeitos à restrição de segurança.
  • Uma pessoa com o papel de administrador é dada autoridade para os recursos seguros.
  • O elemento de login-config é usado para explicar a forma básica de autenticação.

Agora, se nós tentarmos navegar para qualquer URL incluindo o diretório /security, ele iria mostrar uma caixa de diálogo solicitando nome de usuário e senha. Se nós fornecemos um usuário "admin" e a senha "securer", então só teríamos acesso a URL acompanhado por /secured/ * porque acima de nós definimos usuário admin com a função de gerente, que tem permissão para acessar este recurso.

Formulário baseado em autenticação:

Quando usamos o método de formulário baseado em autenticação, deve ser fornecido um formulário de login para solicitar ao usuário um login e senha. A seguir está um código simples de loginpage.jsp para criar um formulário para o mesmo fim:

Listagem 3: Código simples de loginpage.jsp

<html> 
<body bgcolor="#ffffff"> 
   <form method="POST" action="j_security_check"> 
      <table border="0"> 
      <tr> 
      <td>Login</td> 
      <td><input type="text" name="j_username"></td> 
      </tr> 
      <tr> 
      <td>Password</td> 
      <td><input type="password" name="j_password"></td> 
      </tr> 
      </table> 
      <input type="submit" value="Login!"> 
      </center> 
   </form> 
</body> 
</html>

Aqui nós temos que ter certeza de que o formulário de login deve conter elementos de formulário chamado j_username e j_password. A ação no deve ser j_security_check. O formulário dece usar um método GET.

Ao mesmo tempo em que teria de modificar a tag para especificar auth-method como FORM:

Listagem 4: Código auth-method

<web-app> 
... 
    <security-constraint> 
        <web-resource-collection> 
            <web-resource-name> 
               SecuredBookSite 
            </web-resource-name> 
            <url-pattern>/secured/*</url-pattern> 
            <http-method>GET</http-method> 
            <http-method>POST</http-method> 
        </web-resource-collection> 
        <auth-constraint> 
            <description> 
            Let use this app only by managers 
            </description> 
            <role-name>manager</role-name> 
        </auth-constraint> 
    </security-constraint> 
    <security-role> 
       <role-name>manager</role-name> 
    </security-role> 
    <login-config> 
      <auth-method>FORM</auth-method> 
      <form-login-config> 
        <form-login-page>/loginpage.jsp</form-login-page> 
        <form-error-page>/errorpage.jsp</form-error-page> 
      </form-login-config> 
    </login-config> 
... 
</web-app>

Agora, quando tentar acessar qualquer recurso com a URL /secured/ *, será exibido acima formulário pedindo login de usuário e senha. Quando o servidor ver a ação "j_security_check", segue-se um mecanismo interno para verificar o usuário chamador.

Se a autenticação for bem sucedida e o usuário estiver autorizado a acessar o recurso protegido, o servidor usa uma sessão-id para identificar uma sessão de login para o usuário a partir desse ponto. O servidor mantém a sessão de login com um cookie contendo o id da sessão. O servidor retorna o cookie de volta para o cliente, e enquanto o chamador existe este cookie com pedidos frequentes, o servidor vai saber quem é o usuário chamador.

Se o login falhar, o servidor envia de volta a página identificada pela definição de form--página de erro.

Aqui j_security_check é a ação que aplicativos usando formulário baseado em sessão tem que especificar para o formulário de login. Na mesma forma, temos um controle de entrada de texto chamado j_username e um controle de entrada de senha chamado j_password. Quando vemos isso significa que as informações contidas no formulário serão armazenadas no servidor, que irá verificar o login e a senha.

Segurança programática em um Servlet/JSP:

O objeto HttpServletRequest fornece os métodos abaixo, que podem ser usados para obter informações de segurança em tempo de execução:

Método Descrição
String getAuthType() O método getAuthType () resulta um objeto String que representa o nome do esquema de autenticação usado para proteger o Servlet.
boolean isUserInRole(java.lang.String role) O método isUserInRole () retorna um valor booleano: true se o usuário possui determinado role e false se eles não possuem.
String getProtocol() O método getProtocol () retorna um objeto String representando o protocolo que foi usado para enviar a requisição. Este valor pode ser determinado de modo que, se um protocolo de segurança foi utilizado.
boolean isSecure() O método IsSecure () retorna um valor booleano representando se a solicitação foi criada usando HTTPS.
Principle getUserPrinciple() O método getUserPrinciple () resulta java.security.Principle um objeto que contém o nome do usuário autenticado atual.

Listagem 5: Demonstração do método getAuthType

import java.util.*; 
import java.io.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 
import java.security.*; 
public class MyServlet extends HttpServlet { 
     
    public void init(ServletConfig cfg) throws ServletException  
    { 
        super.init(cfg); 
    }  
  
    public void doGet(HttpServletRequest request, HttpServletResponse response)  
        throws IOException, ServletException  
    { 
        response.setContentType("text/html"); 
        PrintWriter out = response.getWriter(); 
  
        out.println("<HTML>"); 
        out.println("<HEAD>"); 
        out.println("<TITLE>"); 
        out.println("User Authentication"); 
        out.println("</TITLE>"); 
        out.println("</HEAD>"); 
        out.println("<BODY>"); 
        out.println("<H1>User Authentication</H1>"); 
  
        String type = request.getAuthType(); 
        out.println("Welcome User<BR>"); 
        out.println("Authentication mechanism: " + type + "<BR>"); 
        Principal p = request.getUserPrincipal(); 
        out.println("Wer username is: " + p.getName() + "<BR>"); 
  
        out.println("</BODY>"); 
        out.println("</HTML>"); 
    }  
}

Saída:

Welcome User
Authentication mechanism:Manager
Wer username is:Davi

Por exemplo, uma JSP com links para páginas de gestores pode ter o seguinte trecho:

Listagem 6: Link para gestores

<% if (request.isUserInRole("manager")) { %> 
<a href="managers/mgrreport.jsp">Manager Report</a> 
<a href="managers/personnel.jsp">Personnel Records</a> 
<% } %>

Ao verificar o papel do usuário em um JSP ou Servlet, podemos personalizar a página da Web para mostrar ao usuário apenas os itens que podem ser usados. Se precisarmos do nome do usuário podemos chamar o método getRemoteUser no objeto da requisição.

Conclusão

Tecnologia de segurança de Java inclui um grande conjunto de APIs, ferramentas e cumprimento de algoritmos de segurança utilizados, protocolos e mecanismos. As APIs de segurança do Java abrange uma ampla gama de áreas, incluindo a infra-estrutura de chave pública, criptografia e autenticação, comunicação fixa e controle de uso. Tecnologia de segurança de Java confere ao programador com uma estrutura de segurança completa para aplicações de escrita, e também concede o usuário ou administrador um conjunto de ferramentas para gerenciar com segurança as aplicações.