JAAS Login - WordPress.com

Transcrição

JAAS Login - WordPress.com
Implementando uma aplicação java segura utilizando
JAAS.
Introdução
Neste documento mostrarei como desenvolver uma simples aplicação
utilizando JAAS (Java Authentication and Authorization Service) e um pouco de JQuery
para realizar a validação de alguns campos.
As tecnologias utilizadas serão:
– JDK 5.0 Update 22 e NetBeans 6.5.1
www.sun.com.br
– MySql 5.0
http://dev.mysql.com/downloads
– TomCat 6.0.18
(Instalado juntamente com o NetBeans)
Let's go..
Com seu JDK e NetBeans já instalado , vamos começar criando um novo
projeto clicando com o botão direito na aba lateral “projetos” e em seguida
selecionando “Java Web” e depois “Aplicação Web” ou então através do menu
“Arquivo” e “Novo Projeto”.
Então de um nome a sua aplicação, com a inicial maiúscula
preferencialmente e clique em “Próximo”.
Se preferir altere o “Caminho do contexto” que será o nome que será
exibido na URL quando executar sua aplicação.
E clique em “Finalizar”.
Então você terá um projeto ao menos parecido com este...
Então vamos dar uma organizada na disposição dos diretórios para que
possamos dar andamento no projeto.
Crie três (3) diretórios dentro de “Páginas Web” com os nomes: “jsp”,
“admin” e “user”, por fim mova a página “index.jsp”, que foi gerad
aautomaticamente pela IDE, para o diretório “jsp”.
Obs: Não tente ainda executar seu projeto, configuraremos o “web.xml”
em instantes.
Veja o que fizemos até agora:
Agora criaremos algumas outras páginas, clicando sobre o diretório de
destino e selecionando “Novo JSP”.
Crie as páginas de forma que fiquem desta maneira:
Dentro do diretório “WEB-INF” você encontrará um arquivo chamado
“web.xml”, ele é responsável pelo mapeamento dos recursos de toda sua
aplicação, e como alteramos o local da página “index.jsp” precisamos alterar
também seu mapa. Veja:
Então execute seu projeto, para conferir se tudo está funcionando
corretamente, em caso positivo, você verá o tão famoso “Hello World !” em seu
browser padrão.
Agora, um pouco de JAAS
O JAAS ou “Java Authentication and Authorization Service” é composto
de um conjunto de API's para distinguir definitivamente a camada de segurança
da camada de aplicação, retirando assim a responsabilidade do desenvolvedor
de manter filtros e ou quaisquer outros métodos de forma programática.
Diz-se que este é um tipo de segurança declarativa, pois, são apenas
declaradas as restrições no arquivo “web.xml” de sua aplicação e no
“server.xml” do servidor web, que em nosso caso é o Apache Tomcat.
Para economizar um pouco de digitação, vou usar uma referência muito
boa retirada do site http://jspbrasil.com.br/mostrar/28 , do autor Gleydson Lima
([email protected]).
Segue o trecho com fonte em itálico...
Conceitos Importantes
Para o bom entendimento da segurança no J2EE é necessário que conheçamos alguns
conceitos importantes. Os conceitos mais importantes são o de role, user, group e realm.
• Role: Um role é um nível de permissão. Usuários podem ter roles diferentes e com acessos
diferentes. Por exemplo, um sistema de gestão da empresa poderia ter os roles:
• Funcionário
• Gerente
• Diretor
• Fornecer
Cada ator interage com o sistema com níveis de permissões diferentes. Um Gerente e o
Diretor têm acesso ao módulo de folha de pagamento, no entanto o Fornecedor e
Funcionário não.
Um role representa, em níveis práticos, o papel que o usuário tem no domínio da empresa.
Provavelmente, no domínio do negócio o funcionário não tem acesso a folha de pagamento
da empresa. Isso deve se refletir no sistema.
• User: Um usuário representa uma entidade com acesso ao sistema. O nível de acesso desse
usuário vai depender do seu role.
O usuário claudio pode ter o role Gerente e o usuário marcos o role Funcionário.
Assim, no acesso ao sistema, o usuário claudio quando tentar acesso o módulo de folha de
pagamento não será barrado pelo servidor de aplicações, permitindo assim que ele possa
acessa-lo. Porém, se o usuário marcos tentar realizar a mesma operação o servidor de
aplicações irá emitir um erro de segurança e não permitirá que se tenha acesso ao módulo.
• Group: Um grupo é associado com um conjunto de roles e todo usuário que é membro do
grupo automaticamente herda os roles associados.
Por exemplo, podemos criar um grupo denominado Gerencia. Os roles pertencentes ao
grupo Gerencia serão Gerente e Diretor. Se colocarmos o usuário carlos pertencente ao
grupo Gerencia, ele herdaria automaticamente todas as permissões do role Gerente e
Diretor.
• Realm: Um conjunto completo de usuários, roles e groups normalmente armazenados em
algum banco de dados.
Existem vários tipos de Realm. Podermos guardar as informações de segurança em um
servidor de diretórios LDAP ou NIS, em arquivos de configurações ou em um banco de
dados.
Roles
Os roles são níveis de permissão que normalmente são associados com partes de URL que
possuem acessos diferentes. Por exemplo, podemos dar acesso a URL
http://www.empresa.com.br/folha-pagamento para somente usuários que possuam o role de diretor
e http://www.empresa.com.br/contra-cheque para usuários que possuam o role de funcionário.
Dessa forma os usuários que possuem o role funcionário não possui acesso à área de
diretor.
Por exemplo, podemos definir esses roles no arquivo web.xml da aplicação, como mostra o
exemplo abaixo:
<security-role>
<description>Diretor da Empresa</description>
<role-name>diretor</role-name>
</security-role>
<security-role>
<description>Funcionário da Empresa</description>
<role-name>funcionario</role-name>
</security-role>
Agora precisamos fazer um mapeamento de usuários com os roles, normalmente em
nível de descritores isso é feito em deployment descriptores específicos do servidor, no caso
do tomcat é o conf/tomcat-users.xml.
<?xml version='1.0'?>
<tomcat-users>
<user username='gleydson' password='abced' roles='diretor,funcionario'/>
<user username='jose' password='qwert' roles='funcionario'/>
</tomcat-users>
Note que um usuário pode ter vários roles, dessa forma este usuário terá acesso à área de
funcionário e diretor.
Referenciando um role existente
È possível adicionar links de roles, como é mostrado abaixo:
<security-role-ref>
<role-name>empregado
<role-link>funcionario
</security-role-ref>
Dessa forma o role empregado passa um link para o role funcionario.
Configurando o acesso a recursos Web
A configuração da segurança declarativa será dada no deployment descriptor (web.xml) da
aplicação e basicamente por três tags XML:
• <login-config>: Configura qual será o modo de requisitar a autenticação ao usuário e de
qual realm o servidor de aplicações irá buscar informações.
• <security-constraint>: Usada para configurar os acessos a um conjunto de recursos
através de mapeamento de URL.
• <security-role>: Representa um conjunto definido de grupos de realm.
Security Constraints
As security constraints determina quem é autorizado a acessar um conjunto de padrões de
URL juntamente com seus métodos de acesso (POST ou GET). Caso você defina um security
constraint para uma determinada URL o container só permitirá acesso a essa URL através de um
usuário autenticado e com o role específico. Caso um outro usuário não autenticado tente acessar
o conteúdo, o servidor irá tentar autenticar este usuário.
Autenticação de Usuários
Existem basicamente cinco tipos de autenticação de usuários como listado abaixo:
• Nenhuma: Usuário não é autenticado.
• HTTP Basic Authentication (<auth-method>BASIC</auth-method>): Este método de
autenticação faz com que o browser solicite usuário e senha para autenticação através de
um formulário proprietário do próprio browser.
• Form-based Authentication (<auth-method>FORM</auth-method>): Este método permite
ao usuário mostrar uma página JSP que será o formulário de autenticação como também
uma página padrão de erros.
<!-- LOGIN AUTHENTICATION -->
<login-config>
<auth-method>FORM</auth-method>
<realm-name>default</realm-name>
<form-login-config>
<form-login-page>login.jsp</form-login-page>
<form-error-page>error.jsp</form-error-page>
</form-login-config>
</login-config>
Toda às vezes que os recursos configurados forem acessados e houver a necessidade de
autenticação o formulário login.jsp será exibido.
• Client-certificate authentication (<auth-method>CLIENT-CERT</auth-method>): Este é o
método mais seguro de autenticação usando SSL e esquemas de troca de certificados para
autenticação.
• Digest Authentication(<auth-method>DIGEST</auth-method>): O método DIGEST é
parecido com o BASIC e FORM, porém as informações de password são enviadas
criptografadas através de algum algoritmo de hashing. Dessa forma a senha trafega
criptografada mesmo em canais não seguros.
Exemplo de uma configuração de web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "http://java.sun.com./dtd/web-app_2_3.dtd">...
<display-name>J2EEBrasilApp</display-name>
<servlet>
<servlet-name>index</servlet-name>
<display-name>index</display-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- REGRAS DE SEGURANÇA -->
<security-constraint>
<web-resource-collection>
<web-resource-name>WRCollection</web-resource-name>
<url-pattern>/sistema/contra-cheque/</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>funcionario</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>WRCollection</web-resource-name>
<url-pattern>/sistema/folha-pagamento/</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>diretor</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- MÉTODO DE LOGIN -->
<login-config>
<realm-name></realm-name>
<auth-method>BASIC</auth-method>
</login-config>
<!-- ROLES DE SEGURANÇA -->
<security-role>
<role-name>diretor</role-name>
</security-role>
<security-role>
<role-name>funcionario</role-name>
</security-role>
Nuss... Quanta informação não é ?
Voltando a nosso projeto, decidi criar um JDBCRealm para coisa ficar
mais interessante ao invés de guardar as informações em arquivos no servidor.
Vamos começar criando o banco que iremos utilizar, utilize seu editor
preferido para realizar esta tarefa, vou mostrar um exemplo de desenho de BD
que fiz, não sou muito bom com isso, mas, funcionou...
create table usuarios(
usu_login varchar(20) primary key,
usu_pass varchar(50) not null,
usu_nome varchar(50) not null,
usu_email varchar(100) not null
) engine= InnoDB;
create table papeis(
pap_descricao varchar(20) not null,
primary key (pap_descricao)
) engine= InnoDB;
create table usupap(
usu_login varchar(20) not null,
pap_descricao varchar(20) not null,
primary key (usu_login, pap_descricao),
foreign key (usu_login) references usuarios (usu_login),
foreign key (pap_descricao) references papeis (pap_descricao)
) engine= InnoDB;
/*Senha = MD5(admin).*/
insert into usuarios values
('admin','21232f297a57a5a743894a0e4a801fc3','ADMINISTRADOR','[email protected]');
/*Senha = MD5(user).*/
insert into usuarios values
('user','ee11cbb19052e40b07aac0ca060c23ee','USUARIO','[email protected]');
insert into papeis values('manager');
insert into papeis values('user');
insert into usupap values('admin','manager');
insert into usupap values('user','user');
Neste momento, você já tem as tabelas criadas e dois papéis já pré-
definidos, “manager” obrigatório na maioria das versões do Tomcat (acho que li
isto em algum lugar...) e “user” que é nosso usuário comum e também dois
usuários “admin”e “user” com seus respectivos papéis e senhas. Neste caso
cada usuário tem apenas um papel, mas poderiam ter quantos fossem
necessários, mas para nossa ilustração, um para cada já é o bastante.
Agora no NetBeans selecione a aba “Serviços” e em seguida o item
“Servidores”, clique com o botão direito do mouse sobre “Apache Tomcat” e
selecione “Editar server.xml”.
Adicione este trecho seu arquivo “server.xml”. Atenção a
“connectionURL” pois ela pode variar dependendo da sua configuração. OBS:
Localize uma tag “<Realm..” , deve ser abaixo da mesma.
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver" digest="MD5"
connectionURL="jdbc:mysql://localhost:3306/securedb"
connectionName="root" connectionPassword=""
userTable="usuarios" userNameCol="usu_login" userCredCol="usu_pass"
userRoleTable="usupap" roleNameCol="pap_descricao"/>
Mais informações em: http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html
Reinicie o servidor, isto pode ser feito através do botão “Reiniciar
servidor” na parte lateral esquerda da aba inferior do próprio NetBeans. Veja:
A partir de agora caso seja solicitado identificação para que possa efetuar
a construção ou execução do projeto, você deve inserir “admin” para usuário e
senha, já que este é o role administrador do Tomcat, como definimos no banco
de dados.
Usaremos o método “FORM” para a autenticação então temos que editar
nossa página de login para que fique dentro do padrão exigido para tal.
Não sou muito bom com design e esse também não nosso foco (ainda
bem...), então construí uma página o mais simples possível. Veja:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
body {
margin:0;
padding:0;
background:#ccc;
text-align:center;
}
label{
display: block;
text-align:left;
}
#pagina {
width: 180px;
margin: 200px auto;
padding: 10px;
text-align:left; /
}
#fields {
padding: 5px;
text-align:center;
}
#butEnviar{
margin-left:125px;
}
</style>
<title>Login</title>
</head>
<body>
<div id="pagina">
<div id="fields">
<form action="j_security_check" method="post">
<label>Usu&aacute;rio</label>
<input id="j_username" name="j_username" type="text">
<label >Senha</label>
<input id="j_password" name="j_password" type="password">
<br>
<input id="butEnviar" type="submit" value="Enviar">
</form>
</div>
</div>
</body>
</html>
Bonita não é...
É importante saber que as propriedades marcadas em vermelho tem que
ter esse nome obrigatoriamente.
E também criaremos uma página de login.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
body {
margin:0;
padding:0;
text-align:center; /
}
#pagina {
width: 100%;
margin:0 auto;
padding: 10px;
text-align:left;
}
#msg {
text-align:center;
color:red;
}
</style>
<title>Erro</title>
</head>
<body>
<div id="pagina">
<div id="msg">
<h1>Voc&ecirc; n&atilde;o tem permiss&atilde;o para acessar este
recurso.</h1>
</div>
</div>
</body>
</html>
As páginas com restrição de acesso podem ser formatadas da forma que
você achar melhor
são elas: “restricted.jsp” (poderia ser uma página de administração) e a outra
“allowed.jsp” (destinada a um usuário específico).
Bem, até aqui já criamos o banco de usuários e permissões, configuramos
o servidor, criamos as páginas de login e erro e já sabemos quem pode acessar
qual página... nós sabemos mas a aplicação não, então vamos voltar ao nosso
arquivo “web.xml”.
Suas configurações devem ser muito parecidas a esta:
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/jsp/login.jsp</form-login-page>
<form-error-page>/jsp/error.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>manager</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>user</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<url-pattern>/user/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
Defimos então que o método de autenticação será o “FORM”, que
somentes os usuários com role “manager” poderão acessar as páginas do
diretório “/admin” e que somente os usuários com role “user” podem acessar o
diretório “/user” e seu conteúdo.
Criei uma página de login apenas com dois links um para a página contida
no diretório “admin” e outro para a página do diretório “user”.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
body {
margin:0;
padding:0;
text-align:center;
}
#pagina {
width: 100px;
margin: 200px auto;
padding: 10px;
text-align:left;
}
#msg {
text-align:center;
}
</style>
<title>Index</title>
</head>
<body>
<div id="pagina">
<div id="msg">
<a href="../admin/restricted.jsp"> <h1>Administrador</h1> </a>
<a href="../user/allowed.jsp"> <h1>Usu&aacute;rio</h1> </a>
</div>
</div>
</body>
</html>
A permissão é mantida na sessão então para alternar entre os tipos
“manager” e “user” você tem duas alternativas: criar um “logout”invalidando a
sessão ou reiniciar seu browser.
Então vamos lá...
Selecione pra onde você deseja ir:
Selecionei administrador e então fui redirecionado para apágina de login.
Digitei o usuário e senha corretamente e...
E estamos na página de administração.
Se tivéssemos inserido um usuário e senha válidos porem sem o nível de
acesso necessário veríamos isso.
Ou se insirido usuário ou senha inválidos....
Então seriamos redirecionados a página de erro...
Bom acho que é isso, fizemos algo bem simples, mas atendendo o
proposto, daqui em diante depende de sua necessidade e imaginação.
Obrigado...
Resolvemos um problema, mas, temos outro.
Rastreando minha interface de rede local e executando nossa aplicação de
login veja o que encontrei...
E@@YSOJ_J/i
##{,POST /admin/j_security_check HTTP/1.1
Host: localhost:8084
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.3) Gecko/20090920 Firefox/
3.5.3 (Swiftfox)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8084/admin/restricted.jsp
Cookie: JSESSIONID=48F5BD75426390B0C427E8CBB97D97ED
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
j_username=admin&j_password=admin
EpV@@""Xgd
##W8SELECT usu_pass FROM usuarios WHERE usu_login = 'admin'
E@@AQ"Xg"
##>defsecuredbusuariosusuariosusu_passusu_pass2!
21232F297a57a5a743894a0e4a801fc3
É isso mesmo que você esta pensando, estes são seu dados de login,
usuário e senha em texto plano e encriptada....
Serei bem rápido nesta parte.
A pergunta:
O que precisamos para estabelecer uma conexão segura para transferir os
dados de nosso login ?
A resposta:
SSL (https).
Faremos aqui uma simulação simples, comece com este comando:
keytool -genkey -keystore sample.keystore -storepass samplepwd -keypass
samplepwd -keyalg RSA -alias sample_key -validity 360 -dname
"cn=SampleGroup,ou=Sample,c=Bebedouro,s=SP,c=BR"
Ele cria um storage com uma chave que usaremos em nosso “certificado”
para possibilitar a execução de uma conexão https.
Agora você tera que editar o arquivo “sever.xml” do Tomcat adicionando
estas linhas:
<Connector protocol="HTTP/1.1" SSLEnabled="true"
port="8443" maxThreads="100" strategy="ms"
maxHttpHeaderSize="8192" emptySessionPath="true"
scheme="https" secure="true" clientAuth="false"
keystoreFile=“seucaminho/sample.keystore"
keystorePass=" samplepwd" sslProtocol = "TLS" />
E por fim adicione isto ao “web.xml” da sua aplicação:
<security-constraint>
<web-resource-collection>
<web-resource-name>app-name</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Note que informamos que todas as páginas de nossa aplicação utilizarão
conexão segura, eta não é uma prática muito performática levando em
consideração o tráfego de rede, então tente aplicar isso somente onde é
realmente necessário.
Quando executar sua aplicação é possível que seja solicitado para que
adicione um exceção de segurança em relação ao certificado que criamos, já
que ele não é assinado por uma entidade certificadora.
Depois de adicionada a exceção, observe que o canto da barra de
navegação do browser muda de formato, veja:
E o rastreio de pacotes usando o Wireshark....
E@@9F. U
&.j&'Mp:JM ).aQVOm~tt0kt
>n<Bk>"]5H242g(BGvU'(w
E }:t,Z$]MB}TWIDr=}H0D%@M{[V+QZ_ZDb`331~zlQRr(wQ`XH3WwJ`=|MJm.qjF9<^yi~$4H`6Sot`n(|lz>g9K#4M^BD
?D47
a' hPp)~/4d~05p=4C.j(6O"i8{3a3I-W$
%dbP\NFefM5I7L<{(Z_!_~J^oiaLM&b-kRoN~xUpMPbE:c$_I26w?Gne//KoB2>
E?W@@" "X3
&.k&.kcommit
EsW@@z"+"Xg
&.k&.k;SELECT pap_descricao FROM usupap WHERE usu_login = 'admin'
EP@@@"X"j
&.k&.kDdefsecuredbusupapusupappap_descricaopap_descricaoPmanager
E?W@@"j"X3
&.k&.kcommit
E?Q@@A]"X"u3
&.k&.k
E@@9 .UHh
&.k&.jQWHTLE_W*+.1nXS\j^g`d5R}[(E:%&cJAb9$IZ ]E{!%J4|H]+
(Qvv:6ZCxyJf9b.b<@&#F)80WV!mcy-5
Já não vemos nossa senha...
FIM
Principais referências
- http://www.paulovittor23.org/2007/10/16/conhecendo-a-seguranca-declarativa-do-java-jaas-–parte-1/
- http://jspbrasil.com.br/mostrar/28
Leandro Alves
::: Java Development
::: Bacharel em Sistemas de Informação
::: Pós graduando em Desenvolvimento de Sistemas para Web
[email protected]

Documentos relacionados

Segurança e controle de erros

Segurança e controle de erros Autorização: perfis de usuário ƒ Uma vez definida a forma de autenticação, é preciso definir perfis de usuário habilitados a acessar os recursos ƒ A declaração de perfis de usuários é feita no web...

Leia mais