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.