• Nenhum resultado encontrado

Aula 09

N/A
N/A
Protected

Academic year: 2021

Share "Aula 09"

Copied!
37
0
0

Texto

(1)

Segurança EJB

(2)

Autenticação e Autorização

• Proteger um aplicativo remete a duas funções principais: autenticação e autorização. • É importante ter certeza de que os usuários terão acesso apenas aos dados e

operações para as quais eles estão credenciados e também garantir que hackers não possam contornar os mecanismos de segurança do aplicativo.

(3)

Autenticação e Autorização

• A autenticação é o processo de verificar a identidade do usuário. Autenticando, você prova ser quem você diz ser.

• Autorização é o processo de determinar se um usuário previamente autenticado possui a permissão de executar uma certa ação.

(4)

Autenticação

• Autenticação

• A especificação EJB não especifica como a autenticação acontece; também não define como o servidor de aplicação armazena e recupera informação de autenticação. Embora defina como informações de segurança são propagadas a partir de um cliente para um servidor.

• O provedor EJB deve decidir como prover esses serviços.

• Na realidade, vamos mostrar um pouco mais que segurança EJB, vamos mostrar segurança JEE.

(5)

Autorização

• Depois que um usuário é autenticado por um mecanismo específico do fornecedor, deve ser verificado se ele está autorizado a invocar um método EJB de um session bean particular (em EJB o controle de acesso tem granularidade de método).

• A autorização é realizada, associando um ou mais papéis com um determinado usuário e, em seguida, atribuindo permissões de método baseadas em papéis. • Papéis são usados para identificar um grupo de usuários – por exemplo,

(6)
(7)
(8)

JAAS

• Segurança EJB é largamente baseada em JAAS (Java Authentication and Authorization Service).

• JAAS essencialmente separa o sistema de autenticação da aplicação Java EE.

JAAS sabe como conversar com sistemas de autenticação como Microsoft’s Active Directory ou Lightweight Directory Access Protocol (LDAP).

O servidor JEE internamente usa JAAS para fazer autorização nas camadas web e EJB.

(9)
(10)

Segurança declarativa EJB

De forma semelhante a CMTs, com a segurança declarativa, você diz ao container o que espera da autorização através de anotações (ou ainda através de arquivos de configuração).

(11)
(12)

Segurança declarativa EJB

A anotação @RunAs é similar ao comando sudo do Unix (permite, por exemplo, executar uma comando como administrador).

(13)

Segurança programática EJB

• Segurança declarativa é poderosa, mas há situações nas quais é necessário um controle maior sobre a segurança. Por exemplo, pode ser necessário alterar o comportamento do método de acordo com o papel do usuário.

• É importante observar que segurança declarativa e programática não são mutuamente excludentes.

(14)
(15)
(16)
(17)

Autenticação no Glassfish

• Vamos criar um exemplo de autenticação utilizando o Glassfish e um banco de dados relacional

No Glassfish, é o que chamaremos de saltRealm.

• Primeiro, serão definidas tabelas em um banco de dados para armazenar informações ligadas aos usuários e grupos.

Segundo, será criada uma biblioteca (um arquivo .jar) que deve conter no mínimo duas classes:

Uma subclasse de com.sun.appserv.security.AppservPasswordLoginModule.

Uma subclasse de com.sun.appserv.security.AppservRealm.

(18)

Tabelas e Campos

TB_USUARIO.TXT_LOGIN: é o login do usuário, que é único.

TB_USUARIO.TXT_PASSWORD: senha em forma de hash criptográfico (Wikipedia: Função_hash_criptográfica).

• TB_USUARIO.TXT_SAL: é o sal. A senha é concatenada com um valor aleatório, não-secreto conhecido como sal, antes de ser aplicada a função hash.

• TB_GRUPO.TXT_NOME: é o nome do grupo, que é único.

(19)

Classes

AppservPasswordLoginModule

• Nossa subclasse terá apenas que sobrescrever um único método:

protected void authenticateUser() throws LoginException;AppservRealm

• Nossa subclasse terá que sobrescrever pelo menos três métodos:

public synchronized void init(Properties properties) throws BadRealmException, NoSuchRealmException; //lê as propriedades de um arquivo XML de

configuração do Glassfish.

public String getJAASContext(); //retorna o nome do realm.

public Enumeration getGroupNames(String username) //retorna uma

(20)

Fragmento de

código da classe

SaltRealm

public class SaltRealm extends AppservRealm {

@Override

public String getJAASContext() {

return "saltRealm";

}

@Override

public Enumeration getGroupNames(String username) { Vector<String> vector = new Vector<String>();

//recupera a lista de grupos através de um SQL. List<String> groups = getGroupList(username);

for (String group : groups) { vector.add(group); } return vector.elements(); } } }

Baixe o código fonte:

https://github.com/marcosifpe/Bib liotecaConsumidor/trunk/mavenpr oject1/saltRealm

(21)

Fragmento de

código da classe

SaltLoginModule

public class SaltLoginModule

extends AppservPasswordLoginModule { @Override

protected void authenticateUser() throws LoginException { SaltRealm realm = (SaltRealm) _currentRealm;

if (realm.authenticateUser(_username, _password)) {

List<String> groupsList =

realm.getGroupList(_username); String[] groups = new String[groupsList.size()];

int i = 0;

for (String group : groupsList) groups[i++] = group;

commitUserAuthentication(groups);

} else { throw new LoginException("Invalid login!"); } }

(22)

Configurações

no Glassfish

<auth-realm

classname="softwarecorporativo.saltrealm.SaltRealm"name="saltRealm"> <property name="jaas-context" value="saltRealm" />

<property name="jta-data-source"value="jdbc/Biblioteca"/> <property name="password-sql-query"

value="SELECT txt_password, txt_sal

FROM tb_usuario WHERE txt_login = ?"

/>

<property name="groups-sql-query" value="SELECT g.txt_nome

FROM tb_usuario u, tb_grupo g, tb_usuario_grupo ug WHERE u.id = ug.id_usuario

AND g.id = ug.id_grupo AND u.txt_login = ?"/> <property name="hash-algorithm"value="SHA-256" /> <property name="charset"value="UTF-8" />

</auth-realm>

O arquivo

<glassfish-home>\domains\domain1\config\ domain.xml deve ser alterado com o realm criado.

(23)

Configurações no Glassfish

• Ao arquivo <glassfish-home>\domains\domain1\config\login.conf deve ser adicionado o seguinte valor:

saltRealm {

softwarecorporativo.saltrealm.SaltLoginModule required; };

• Para possibilitar a realização do login de forma programática (a que vamos utilizar), é necessário adicionar a seguinte linha ao arquivo

<glassfish-home>\domains\domain1\config\server.policy:

grant codeBase "file:jar-file-path" {

permission com.sun.appserv.security.ProgrammaticLoginPermission "login"; };

(24)

Configurações na

Aplicação

<security-role-mapping>

<!-- utilizado na aplicação JEE -->

<role-name>usuario</role-name>

<!-- recuperado do banco de dados via “realm” -->

<group-name>usr</group-name> </security-role-mapping>

<security-role-mapping>

<role-name>administrador</role-name> <group-name>admin</group-name> </security-role-mapping>

• No arquivo WEB-INF\glassfish-web.xml, adicionar os papéis da aplicação JEE.

• Observe que role-name é o nome do papel na aplicação e

group-name é o nome do grupo que é recuperado do realm.

• Baixe a aplicação em:

https://github.com/marcosifpe/Bibl ioteca/

(25)

Configurações na

Aplicação

<login-config>

<auth-method>FORM</auth-method> <realm-name>saltRealm</realm-name> <form-login-config>

<form-login-page>/faces/publico/login.xhtml</form-login-page> <form-error-page>/faces/publico/login.xhtml</form-error-page> </form-login-config>

</login-config>

• No arquivo WEB-INF\glassfish-web.xml, é necessário informar como vai ser realizado o login. • No caso, o login será realizado

através de um form, em uma página

xhtml.

O realm que será utilizado para autenticação é o saltRealm. • Para mais informações, ver

documentação em:

https://docs.oracle.com/cd/E13222 _01/wls/docs81/webapp/web_xml. html#1019996

(26)

Configurações na

Aplicação

<security-constraint>

<display-name>Páginas Administrativas</display-name> <web-resource-collection>

<web-resource-name>Área Protegida</web-resource-name> <description>Área Protegida</description>

<url-pattern>/faces/admin/*</url-pattern> <http-method>GET</http-method>

<http-method>POST</http-method>

<!-- Demais métodos HTTP omitidos por motivo de espaço. -->

</web-resource-collection> <auth-constraint>

<description/> <!– Apenas administradores terão acesso. -->

<role-name>administrador</role-name> </auth-constraint>

<user-data-constraint> <!-- Será utilizado HTTPS. -->

<transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint>

</security-constraint>

• Ainda no arquivo WEB-INF\glassfish-web.xml, é necessário informar quais papéis da aplicação JEE terão acesso a que áreas (páginas) da aplicação. • Para mais informações, ver

documentação em:

https://docs.oracle.com/cd/E13222_ 01/wls/docs81/webapp/web_xml.ht ml#1017885

(27)

Páginas

Administrativas

• As páginas listadas na figura ao lado foram protegidas através do web-resource-collection da página anterior.

(28)

Segurança

Declarativa em

EJB’s

@Stateless @LocalBean

@DeclareRoles({ADMINISTRADOR, USUARIO}) //Informa os papéis utilizados neste EJB.

public class LivroService extendsService<Livro> {

@RolesAllowed({ADMINISTRADOR}) //Apenas administradores podem salvar livros.

public void salvar(Livro livro) {

checkExistence(LIVRO_POR_ISBN, livro.getIsbn()); entityManager.persist(livro);

}

@TransactionAttribute(SUPPORTS)

@RolesAllowed({USUARIO}) //Apenas usuários podem consulta a lista de livros.

public List<Livro> getLivros() {

returngetResultList(Livro.LIVROS); }

@TransactionAttribute(SUPPORTS) @PermitAll //O método é de livre acesso.

public Livro getLivro(String isbn) {

returngetSingleResult(LIVRO_POR_ISBN, new Object[]{isbn}); } } • As anotações @DeclareRoles, @RolesAllowed e @PermitAll , no código ao lado, permitem a segurança declarativa (relativa à

(29)

Segurança

Programática

em EJB’s

@Stateless @LocalBean @TransactionManagement(CONTAINER)

public class EditoraServiceextendsService<Editora> { @Resource private SessionContext sessionContext; @TransactionAttribute(REQUIRED)

public void salvar(Editora editora) {

//Apenas administradores podem salvar uma editora.

if(sessionContext.isCallerInRole(ADMINISTRADOR)) {

checkExistence(EDITORA_POR_NOME, editora.getNome()); entityManager.persist(editora);

} else throw new EJBAccessException(); }

@TransactionAttribute(SUPPORTS)

public List<Editora> getEditoras() {

returngetResultList(EDITORAS); } } • Observe o objeto SessionContext e a invocação do método sessionContext.isCallerInRole (ADMINISTRADOR)

(30)

Captcha

•Até o momento, nossa aplicação está utilizando HTTPS, autenticação e autorização JEE. •No entanto, desejamos ainda que um robô não consiga realizar autenticação no formulário

web. Logo, utilizaremos um captcha (https://pt.wikipedia.org/wiki/CAPTCHA) na nossa aplicação.

Mais especificamente, utilizaremos o Google reCaptcha. Mais informações em:

(31)

reCaptcha

<context-param>

<param-name>CAPTCHA_URL</param-name> <param-value>

https://www.google.com/recaptcha/api/siteverify </param-value>

</context-param> <context-param>

<param-name>PUBLIC_CAPTCHA_KEY</param-name> <param-value>*******************</param-value> </context-param>

<context-param>

<param-name>PRIVATE_CAPTCHA_KEY</param-name> <param-value>*******************</param-value> </context-param>

•Após ter se registrado no

Google reCaptcha, o usuário

recebe uma chave pública e uma secreta para utilizar o

reCaptcha na aplicação.

•Na aplicação, armazenaremos essas chaves no arquivo

web.xml.

•A url servirá para acessarmos um webservice do Google que fará a verificação do desafio do

(32)
(33)

Login com reCaptcha

É necessário adicionar, na página de login (login.xhtml), um javascript e um div, conforme explicado na documentação disponível no site da Google.

<script src='https://www.google.com/recaptcha/api.js' /> <div class="g-recaptcha" data-sitekey= "#{facesContext.externalContext.getInitParameter('PUBLIC_CAPTCHA_KEY')}“ />

(34)

Login com reCaptcha

O Google disponibiliza um webservice via url

https://www.google.com/recaptcha/api/siteverify para fazer a verificação.

A aplicação que utiliza reCaptcha deve enviar os parâmetros requeridos e receberá uma resposta em formato JSON.

(35)

Login com reCaptcha

Na Biblioteca EJB3, a classe jsf.beans.Recaptcha é responsável conectar o webservice do Google e verificar se a resposta JSON foi true. Ou seja, se o usuário respondeu corretamente ao desafio do reCaptcha.

(36)

Fragmento de

Código da Classe

LoginBean

public String login() {

try {

facesContext = FacesContext.getCurrentInstance(); Recaptcha recaptcha = new Recaptcha(facesContext);

if (recaptcha.validar()) { //verifica o captcha

HttpServletRequest request = (HttpServletRequest)

facesContext.getExternalContext().getRequest(); request.login(usuario, senha); //tenta realizar o login

facesContext.getExternalContext().getSession(true); } else { //caso o captcha falhe

return "falha"; //tratamento de mensagem de erro omitido }

} catch (ServletException ex) { //caso o login falhe

return "falha"; //tratamento de mensagem de erro omito. }

return "sucesso"; }

Observe que usuario e senha são atributos do bean jsf gerenciado

jsf.beans.LoginBean e passados via

página login.xhtml.

• Após verificar se a informação do

captcha é válido, é realizado o login através da invocação request.login(usuario, senha).

• Esse login será realizado utilizando a validação de saltRealm.

(37)

Fragmento de

Código da Classe

LogoutBean

@ManagedBean(name = "logoutBean") @ViewScoped

public class LogoutBean implements Serializable {

public String logout() throwsServletException {

FacesContext fc = FacesContext.getCurrentInstance(); HttpSession session =

(HttpSession) fc.getExternalContext().getSession(false);

if(session != null) {

session.invalidate(); //Invalida a sessão do usuário.

}

HttpServletRequest request =

(HttpServletRequest) fc.getExternalContext().getRequest(); request.logout(); //Realiza o logout no servidor JEE.

return "sair"; }

}

• Para sair da aplicação, dois passos são necessários:

1. invalidar o HttpSession associado ao usuário;

2. Realizar o logout via

HttpServletRequest, que retira as

informações de indentidade do usuário associadas correntemente ao servidor JEE.

Referências

Documentos relacionados

Também, em boa verdade, e como é jurisprudência da Relação de Évora, deve ser tido como irrelevante o argumento de que se presume do mandato oneroso, conferido

Projeto experimental apresentado no curso de graduação em Comunicação Social – Produção Editorial, do Departamento de Ciências da Comunicação da Universidade

A figura 04 mostra o comportamento temporal dos casos novos desde o início da pandemia no Piauí em uma curva logarítmica, utilizando a média móvel de sete dias.. Como

TORNA DECRETO SEM EFEITO O Prefeito Municipal de Afonso Cláudio, Estado do Espírito Santo, no uso de atribuições que lhe são conferidas; e Considerando que a candidata nomeada

As Empresas pagarão aos seus empregados que tenham filho excepcional, comprovadamente, bem como àqueles incapacitados para atividade laboral, um auxílio mensal

segredo para uma conversa entre cavalheiros não se tornar uma briga de boteco é a seguinte: mire na ideia e, caso você discorde muito dela, odeie-a, mas tenha na outra pessoa

Assim como um modelo ARMA pode ser mais parcimonioso no sentido de apresentar menos parˆ ametros a serem estimados do que modelos AR ou MA, um modelo GARCH pode ser usado para

Com este requisito em mente, alguns protocolos para escalonamento particionado em multiprocessadores foram propostos, como o Multiprocessor Priority Ceiling Protocol (MPCP),