From edecdf07a7240dbf798361f533148eed424bea47 Mon Sep 17 00:00:00 2001 From: Cleverson Sacramento Date: Fri, 17 Oct 2014 09:13:52 -0300 Subject: [PATCH] Melhoria nos filtros de autenticação --- impl/core/src/main/resources/demoiselle-core-bundle.properties | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------ impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/AbstractHTTPAuthorizationFilter.java | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------- impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/BasicAuthFilter.java | 19 +++++++++---------- impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/Token.java | 10 ++++++---- impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/TokenAuthFilter.java | 48 +++++++++++++++++++++++++++++++++++++----------- 5 files changed, 208 insertions(+), 134 deletions(-) diff --git a/impl/core/src/main/resources/demoiselle-core-bundle.properties b/impl/core/src/main/resources/demoiselle-core-bundle.properties index 9f371a4..1407eef 100644 --- a/impl/core/src/main/resources/demoiselle-core-bundle.properties +++ b/impl/core/src/main/resources/demoiselle-core-bundle.properties @@ -17,112 +17,112 @@ # or write to the Free Software Foundation, Inc., 51 Franklin Street, # Fifth Floor, Boston, MA 02110-1301, USA. # ---------------------------------------------------------------------------- -# Este arquivo é parte do Framework Demoiselle. +# Este arquivo \ufffd parte do Framework Demoiselle. # -# O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou -# modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação +# O Framework Demoiselle \ufffd um software livre; voc\ufffd pode redistribu\ufffd-lo e/ou +# modific\ufffd-lo dentro dos termos da GNU LGPL vers\ufffdo 3 como publicada pela Funda\ufffd\ufffdo # do Software Livre (FSF). # -# Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA -# GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou -# APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português +# Este programa \ufffd distribu\ufffddo na esperan\ufffda que possa ser \ufffdtil, mas SEM NENHUMA +# GARANTIA; sem uma garantia impl\ufffdcita de ADEQUA\ufffd\ufffdO a qualquer MERCADO ou +# APLICA\ufffd\ufffdO EM PARTICULAR. Veja a Licen\ufffda P\ufffdblica Geral GNU/LGPL em portugu\ufffds # para maiores detalhes. # -# Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título -# "LICENCA.txt", junto com esse programa. Se não, acesse -# ou escreva para a Fundação do Software Livre (FSF) Inc., +# Voc\ufffd deve ter recebido uma c\ufffdpia da GNU LGPL vers\ufffdo 3, sob o t\ufffdtulo +# "LICENCA.txt", junto com esse programa. Se n\ufffdo, acesse +# ou escreva para a Funda\ufffd\ufffdo do Software Livre (FSF) Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. version=${project.version} -engine-on=Iniciando o Demoiselle Framework ${project.version} -resource-not-found=Arquivo {0} n\u00E3o foi encontrado -key-not-found=A chave {0} n\u00E3o foi encontrada -ambiguous-strategy-resolution=Foi detectada ambiguidade da interface {0} com as seguintes implementa\u00E7\u00F5es\: {1}. Para resolver o conflito, defina explicitamente a implementa\u00E7\u00E3o no demoiselle.properties. -ambiguous-bean-resolution=Falha ao obter {0} pois foi detectada ambiguidade nas seguintes implementa\u00E7\u00F5es\: {1} -bean-not-found=Voc\u00EA est\u00E1 tentando obter um objeto n\u00E3o reconhecido pelo CDI via Beans.getReference({0}) -store-not-found=O objeto do tipo [{0}] n\u00E3o pode ser armazenado no escopo indicado\: {1} -more-than-one-exceptionhandler-defined-for-same-class=Foi definido mais de um m\u00E9todo na classe {0} para tratar a exce\u00E7\u00E3o {1} -handling-exception=Tratando a exce\u00E7\u00E3o {0} +engine-on=Iniciando o Demoiselle Framework ${project.version} (Malkovich) +resource-not-found=Arquivo {0} n\u00e3o foi encontrado +key-not-found=A chave {0} n\u00e3o foi encontrada +ambiguous-strategy-resolution=Foi detectada ambiguidade da interface {0} com as seguintes implementa\u00e7\u00f5es\: {1}. Para resolver o conflito, defina explicitamente a implementa\u00e7\u00e3o no demoiselle.properties. +ambiguous-bean-resolution=Falha ao obter {0} pois foi detectada ambiguidade nas seguintes implementa\u00e7\u00f5es\: {1} +bean-not-found=Voc\u00ea est\u00e1 tentando obter um objeto n\u00e3o reconhecido pelo CDI via Beans.getReference({0}) +store-not-found=O objeto do tipo [{0}] n\u00e3o pode ser armazenado no escopo indicado\: {1} +more-than-one-exceptionhandler-defined-for-same-class=Foi definido mais de um m\u00e9todo na classe {0} para tratar a exce\u00e7\u00e3o {1} +handling-exception=Tratando a exce\u00e7\u00e3o {0} taking-off=O Demoiselle ${project.version} decolou engine-off=Desligando os motores do Demoiselle ${project.version} -setting-up-bean-manager=BeanManager dispon\u00EDvel atrav\u00E9s do utilit\u00E1rio {0} +setting-up-bean-manager=BeanManager dispon\u00edvel atrav\u00e9s do utilit\u00e1rio {0} -user-transaction-lookup-fail=N\u00E3o foi encontrada nenhuma transa\u00E7\u00E3o com o nome {0} no contexto JNDI -transactional-execution=Execu\u00E7\u00E3o transacional de {0} -begin-transaction=Transa\u00E7\u00E3o iniciada -transaction-marked-rollback=Transa\u00E7\u00E3o marcada para rollback [{0}] -transaction-already-finalized=A transa\u00E7\u00E3o j\u00E1 havia sido finalizada -transaction-commited=Transa\u00E7\u00E3o finalizada com sucesso -transaction-rolledback=Transa\u00E7\u00E3o finalizada com rollback +user-transaction-lookup-fail=N\u00e3o foi encontrada nenhuma transa\u00e7\u00e3o com o nome {0} no contexto JNDI +transactional-execution=Execu\u00e7\u00e3o transacional de {0} +begin-transaction=Transa\u00e7\u00e3o iniciada +transaction-marked-rollback=Transa\u00e7\u00e3o marcada para rollback [{0}] +transaction-already-finalized=A transa\u00e7\u00e3o j\u00e1 havia sido finalizada +transaction-commited=Transa\u00e7\u00e3o finalizada com sucesso +transaction-rolledback=Transa\u00e7\u00e3o finalizada com rollback bootstrap.configuration.processing=Processando {0} -bootstrap-context-already-managed=O contexto {0} para o escopo {1} j\u00E1 foi adicionado +bootstrap-context-already-managed=O contexto {0} para o escopo {1} j\u00e1 foi adicionado bootstrap-context-added=Adicionando o contexto {0} para o escopo {1} -loading-configuration-class=Carregando a classe de configura\u00E7\u00E3o {0} +loading-configuration-class=Carregando a classe de configura\u00e7\u00e3o {0} configuration-field-loaded={0}: {2} -configuration-attribute-is-mandatory=A configura\u00E7\u00E3o {0} \u00E9 obrigat\u00F3ria, mas n\u00E3o foi encontrada em {1} -configuration-name-attribute-cant-be-empty=A nota\u00E7\u00E3o @Name n\u00E3o pode estar em branco -configuration-generic-extraction-error=Ocorreu um erro durante a extra\u00E7\u00E3o do tipo {0} com o extrator {1} -configuration-dot-after-prefix=N\u00E3o \u00E9 necess\u00E1rio adicionar o ponto ap\u00F3s o prefixo para uma classe de configura\u00E7\u00E3o. \u00C9 recomendado que sejam retirados, pois poder\u00E3o causar erros em vers\u00F5es futuras do Framework. -configuration-key-not-found={0}\: [n\u00E3o encontrada] -configuration-extractor-not-found=N\u00E3o foi poss\u00EDvel encontrar a classe extratora para o atributo {0}. Implemente a interface {1} para criar sua classe extratora. -configuration-not-conversion=N\u00E3o \u00E9 poss\u00EDvel converter o valor {0} para o tipo {1} +configuration-attribute-is-mandatory=A configura\u00e7\u00e3o {0} \u00e9 obrigat\u00f3ria, mas n\u00e3o foi encontrada em {1} +configuration-name-attribute-cant-be-empty=A nota\u00e7\u00e3o @Name n\u00e3o pode estar em branco +configuration-generic-extraction-error=Ocorreu um erro durante a extra\u00e7\u00e3o do tipo {0} com o extrator {1} +configuration-dot-after-prefix=N\u00e3o \u00e9 necess\u00e1rio adicionar o ponto ap\u00f3s o prefixo para uma classe de configura\u00e7\u00e3o. \u00c9 recomendado que sejam retirados, pois poder\u00e3o causar erros em vers\u00f5es futuras do Framework. +configuration-key-not-found={0}\: [n\u00e3o encontrada] +configuration-extractor-not-found=N\u00e3o foi poss\u00edvel encontrar a classe extratora para o atributo {0}. Implemente a interface {1} para criar sua classe extratora. +configuration-not-conversion=N\u00e3o \u00e9 poss\u00edvel converter o valor {0} para o tipo {1} -transaction-not-defined=Nenhuma transa\u00E7\u00E3o foi definida. Para utilizar @{0} \u00E9 preciso definir a propriedade frameworkdemoiselle.transaction.class com a estrat\u00E9gia de transa\u00E7\u00E3o desejada no arquivo demoiselle.properties -executing-all=Executando m\u00E9todos anotados com @{0} -custom-context-selected=Produzindo inst\u00E2ncia do contexto {0} +transaction-not-defined=Nenhuma transa\u00e7\u00e3o foi definida. Para utilizar @{0} \u00e9 preciso definir a propriedade frameworkdemoiselle.transaction.class com a estrat\u00e9gia de transa\u00e7\u00e3o desejada no arquivo demoiselle.properties +executing-all=Executando m\u00e9todos anotados com @{0} +custom-context-selected=Produzindo inst\u00e2ncia do contexto {0} custom-context-was-activated=O contexto {0} foi ativado para o escopo {1} custom-context-was-deactivated=O contexto {0} foi desativado para o escopo {1} -custom-context-already-activated=N\u00E3o foi poss\u00EDvel ativar o contexto {0}, o escopo {1} j\u00E1 est\u00E1 ativo no contexto {2} -custom-context-not-found=N\u00E3o foi encontrado um contexto gerenciado do tipo [{0}] para o escopo [{1}] -custom-context-manager-not-initialized=ContextManager n\u00E3o foi inicializado. Chame [initialize] ao capturar o evento [AfterBeanDiscovery] em uma extens\u00E3o CDI +custom-context-already-activated=N\u00e3o foi poss\u00edvel ativar o contexto {0}, o escopo {1} j\u00e1 est\u00e1 ativo no contexto {2} +custom-context-not-found=N\u00e3o foi encontrado um contexto gerenciado do tipo [{0}] para o escopo [{1}] +custom-context-manager-not-initialized=ContextManager n\u00e3o foi inicializado. Chame [initialize] ao capturar o evento [AfterBeanDiscovery] em uma extens\u00e3o CDI error-creating-new-instance-for=Error creating a new instance for "{0}" executed-successfully={0} execultado com sucesso -must-declare-one-single-parameter=Voc\u00EA deve declarar um par\u00E2metro \u00FAnico em {0} -loading-default-transaction-manager=Carregando o gerenciador de transa\u00E7\u00E3o padr\u00E3o {0} -results-count-greater-page-size=Quantidade de resultados {0} \u00E9 maior que o tamanho da p\u00E1gina {1} -page-result=Resultado paginado [p\u00E1gina\={0}, total de resultados\={1}] -page=P\u00E1gina [n\u00FAmero\={0}, tamanho\={1}] +must-declare-one-single-parameter=Voc\u00ea deve declarar um par\u00e2metro \u00fanico em {0} +loading-default-transaction-manager=Carregando o gerenciador de transa\u00e7\u00e3o padr\u00e3o {0} +results-count-greater-page-size=Quantidade de resultados {0} \u00e9 maior que o tamanho da p\u00e1gina {1} +page-result=Resultado paginado [p\u00e1gina\={0}, total de resultados\={1}] +page=P\u00e1gina [n\u00famero\={0}, tamanho\={1}] processing=Processando\: {0} -processing-fail=Falha no processamento devido a uma exce\u00E7\u00E3o lan\u00E7ada pela aplica\u00E7\u00E3o +processing-fail=Falha no processamento devido a uma exce\u00e7\u00e3o lan\u00e7ada pela aplica\u00e7\u00e3o for= \ para\: -file-not-found=O arquivo {0} n\u00E3o foi encontrado +file-not-found=O arquivo {0} n\u00e3o foi encontrado adding-message-to-context=Adicionando uma mensagem no contexto: [{0}] -access-checking=Verificando permiss\u00E3o do usu\u00E1rio {0} para executar a a\u00E7\u00E3o {1} no recurso {2} -access-allowed=O usu\u00E1rio {0} acessou o recurso {2} com a a\u00E7\u00E3o {1} -access-denied=O usu\u00E1rio {0} n\u00E3o possui permiss\u00E3o para executar a a\u00E7\u00E3o {1} no recurso {2} -access-denied-ui=Voc\u00EA n\u00E3o est\u00E1 autorizado a executar a a\u00E7\u00E3o {1} no recurso {0} -authorizer-not-defined=Nenhuma regra de resolu\u00E7\u00E3o de permiss\u00F5es foi definida. Para utilizar @{0} \u00E9 preciso definir a propriedade frameworkdemoiselle.security.authorizer.class como regra de resolu\u00E7\u00E3o de permiss\u00F5es desejada no arquivo demoiselle.properties. -user-not-authenticated=Usu\u00E1rio n\u00E3o autenticado -invalid-credentials=Usu\u00E1rio ou senha inv\u00E1lidos -has-role-verification=Verificando se o usu\u00E1rio {0} possui a(s) role(s)\: {1} -does-not-have-role=Usu\u00E1rio {0} n\u00E3o possui a(s) role(s)\: {1} -does-not-have-role-ui=Para acessar este recurso \u00E9 necess\u00E1rio ser {0} -user-has-role=Usu\u00E1rio {0} possui a(s) role(s)\: {1} +access-checking=Verificando permiss\u00e3o do usu\u00e1rio {0} para executar a a\u00e7\u00e3o {1} no recurso {2} +access-allowed=O usu\u00e1rio {0} acessou o recurso {2} com a a\u00e7\u00e3o {1} +access-denied=O usu\u00e1rio {0} n\u00e3o possui permiss\u00e3o para executar a a\u00e7\u00e3o {1} no recurso {2} +access-denied-ui=Voc\u00ea n\u00e3o est\u00e1 autorizado a executar a a\u00e7\u00e3o {1} no recurso {0} +authorizer-not-defined=Nenhuma regra de resolu\u00e7\u00e3o de permiss\u00f5es foi definida. Para utilizar @{0} \u00e9 preciso definir a propriedade frameworkdemoiselle.security.authorizer.class como regra de resolu\u00e7\u00e3o de permiss\u00f5es desejada no arquivo demoiselle.properties. +user-not-authenticated=Usu\u00e1rio n\u00e3o autenticado +invalid-credentials=Usu\u00e1rio ou senha inv\u00e1lidos +has-role-verification=Verificando se o usu\u00e1rio {0} possui a(s) role(s)\: {1} +does-not-have-role=Usu\u00e1rio {0} n\u00e3o possui a(s) role(s)\: {1} +does-not-have-role-ui=Para acessar este recurso \u00e9 necess\u00e1rio ser {0} +user-has-role=Usu\u00e1rio {0} possui a(s) role(s)\: {1} -authenticator-not-defined=Nenhum mecanismo de autentica\u00E7\u00E3o foi definido. Para utilizar {0} \u00E9 preciso definir a propriedade frameworkdemoiselle.security.authenticator.class como mecanismo de autentica\u00E7\u00E3o desejado no arquivo demoiselle.properties. +authenticator-not-defined=Nenhum mecanismo de autentica\u00e7\u00e3o foi definido. Para utilizar {0} \u00e9 preciso definir a propriedade frameworkdemoiselle.security.authenticator.class como mecanismo de autentica\u00e7\u00e3o desejado no arquivo demoiselle.properties. management-notification-attribute-changed=O atributo [{0}] da classe gerenciada [{1}] foi alterado -management-null-class-defined=O controlador de gerenciamento informado n\u00E3o pode ser [null] +management-null-class-defined=O controlador de gerenciamento informado n\u00e3o pode ser [null] management-abstract-class-defined=O controlador de gerenciamento [{0}] precisa ser uma classe concreta management-no-annotation-found=Classe {0} precisa ser anotada com @ManagementController -management-invalid-property-no-getter-setter=Falha ao inicializar classe gerenciada {0}, n\u00E3o foi encontrado um m\u00E9todo get ou m\u00E9todo set para a propriedade {1} -management-invalid-property-as-operation=Falha ao inicializar classe gerenciada {0}, n\u00E3o \u00E9 poss\u00EDvel declarar uma propriedade cujo m\u00E9todo get ou set \u00E9 uma opera\u00E7\u00E3o +management-invalid-property-no-getter-setter=Falha ao inicializar classe gerenciada {0}, n\u00e3o foi encontrado um m\u00e9todo get ou m\u00e9todo set para a propriedade {1} +management-invalid-property-as-operation=Falha ao inicializar classe gerenciada {0}, n\u00e3o \u00e9 poss\u00edvel declarar uma propriedade cujo m\u00e9todo get ou set \u00e9 uma opera\u00e7\u00e3o management-introspection-error=Erro ao ler atributos da classe gerenciada {0} -management-type-not-found=A classe gerenciada informada n\u00E3o existe\: {0} -management-invoke-error=Erro ao tentar invocar a opera\u00E7\u00E3o "{0}" da classe gerenciada, a opera\u00E7\u00E3o n\u00E3o foi encontrada -management-write-value-error=N\u00E3o foi poss\u00EDvel definir um valor para a propriedade {0} -management-read-value-error=N\u00E3o foi poss\u00EDvel ler o valor da propriedade {0} +management-type-not-found=A classe gerenciada informada n\u00e3o existe\: {0} +management-invoke-error=Erro ao tentar invocar a opera\u00e7\u00e3o "{0}" da classe gerenciada, a opera\u00e7\u00e3o n\u00e3o foi encontrada +management-write-value-error=N\u00e3o foi poss\u00edvel definir um valor para a propriedade {0} +management-read-value-error=N\u00e3o foi poss\u00edvel ler o valor da propriedade {0} management-debug-acessing-property=Acessando propriedade {0} da classe gerenciada {1} management-debug-setting-property=Definindo novo valor para propriedade {0} da classe gerenciada {1} -management-debug-invoking-operation=Invocando opera\u00E7\u00E3o {0} da classe gerenciada {1} +management-debug-invoking-operation=Invocando opera\u00e7\u00e3o {0} da classe gerenciada {1} management-debug-starting-custom-context=Levantando contexto {0} para executar comando na classe gerenciada {1} management-debug-stoping-custom-context=Desligando contexto {0} para classe gerenciada {1} management-debug-registering-managed-type=Registrando classe gerenciada [{0}] -management-debug-processing-management-extension=Processando extens\u00E3o de gerenciamento [{0}] -management-debug-removing-management-extension=Desativando extens\u00E3o de gerenciamento [{0}] -management-validation-constraint-violation=Ocorreu um erro de valida\u00E7\u00E3o na classe [{0}] ao definir um valor para a propriedade [{1}]\: [{2}] -management-validation-validator-not-found=Nenhum provedor de valida\u00E7\u00E3o de beans encontrado, as anota\u00E7\u00F5es de valida\u00E7\u00E3o n\u00E3o ser\u00E3o processadas +management-debug-processing-management-extension=Processando extens\u00e3o de gerenciamento [{0}] +management-debug-removing-management-extension=Desativando extens\u00e3o de gerenciamento [{0}] +management-validation-constraint-violation=Ocorreu um erro de valida\u00e7\u00e3o na classe [{0}] ao definir um valor para a propriedade [{1}]\: [{2}] +management-validation-validator-not-found=Nenhum provedor de valida\u00e7\u00e3o de beans encontrado, as anota\u00e7\u00f5es de valida\u00e7\u00e3o n\u00e3o ser\u00e3o processadas diff --git a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/AbstractHTTPAuthorizationFilter.java b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/AbstractHTTPAuthorizationFilter.java index f523af3..aad9265 100644 --- a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/AbstractHTTPAuthorizationFilter.java +++ b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/AbstractHTTPAuthorizationFilter.java @@ -36,9 +36,11 @@ */ package br.gov.frameworkdemoiselle.security; +import static java.util.regex.Pattern.CASE_INSENSITIVE; import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; import java.io.IOException; +import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,18 +69,52 @@ public abstract class AbstractHTTPAuthorizationFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - - RESTSecurityConfig config = Beans.getReference(RESTSecurityConfig.class); - - if (request instanceof HttpServletRequest && isActive(config) - && isSupported(getAuthHeader((HttpServletRequest) request))) { + + if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { + doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain); + } else { + chain.doFilter(request, response); + } + + // boolean processed = false; + // + // if (request instanceof HttpServletRequest) { + // HttpServletRequest httpRequest = (HttpServletRequest) request; + // HttpServletResponse httpResponse = (HttpServletResponse) response; + // + // String authHeader = getAuthHeader(httpRequest); + // String httpCredentials = extractCredentials(authHeader); + // + // RESTSecurityConfig config = Beans.getReference(RESTSecurityConfig.class); + // if (isActive(config) && isSupported(httpCredentials)) { + // processed = true; + // + // try { + // performLogin(httpCredentials, httpRequest, httpResponse); + // chain.doFilter(httpRequest, httpResponse); + // performLogout(httpCredentials, httpRequest, httpResponse); + // + // } catch (InvalidCredentialsException cause) { + // setUnauthorizedStatus(httpResponse, cause); + // } + // } + // } + // + // if (!processed) { + // chain.doFilter(request, response); + // } + } + + protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + if (isActive() && isSupported(request)) { try { - performLogin((HttpServletRequest) request); - chain.doFilter((HttpServletRequest) request, (HttpServletResponse) response); - performLogout(); + performLogin(request, response); + chain.doFilter(request, response); + performLogout(request, response); } catch (InvalidCredentialsException cause) { - setUnauthorizedStatus((HttpServletResponse) response, cause); + setUnauthorizedStatus(response, cause); } } else { @@ -86,27 +122,54 @@ public abstract class AbstractHTTPAuthorizationFilter implements Filter { } } - private String getAuthHeader(HttpServletRequest request) { - String result = request.getHeader("Authorization"); - return (result == null ? request.getHeader("authorization") : result); + protected String getAuthHeader(HttpServletRequest request) { + String value = null; + + for (final Enumeration names = request.getHeaderNames(); names.hasMoreElements();) { + String name = names.nextElement(); + + if ("authorization".equalsIgnoreCase(name)) { + value = request.getHeader(name); + break; + } + } + + return value; + } + + protected String getAuthData(HttpServletRequest request) throws InvalidCredentialsException { + String authData = null; + String authHeader = getAuthHeader(request); + String type = getType(); + + if (!Strings.isEmpty(type) && !Strings.isEmpty(authHeader)) { + String regexp = "^" + type + "[ \\n]+(.+)$"; + Pattern pattern = Pattern.compile(regexp, CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(authHeader); + + if (matcher.matches()) { + authData = matcher.group(1); + } + } + + return authData; } - protected abstract boolean isSupported(String authHeader); + protected boolean isSupported(HttpServletRequest request) { + String data = getAuthData(request); + return !Strings.isEmpty(data); + } - protected abstract boolean isActive(RESTSecurityConfig config); + protected abstract boolean isActive(); - protected abstract void prepareForLogin(); + protected abstract String getType(); - private void performLogin(HttpServletRequest request) { - prepareForLogin(); + protected void performLogin(HttpServletRequest request, HttpServletResponse response) { Beans.getReference(SecurityContext.class).login(); } - protected abstract void prepareForLogout(); - - private void performLogout() { + protected void performLogout(HttpServletRequest request, HttpServletResponse response) { if (Beans.getReference(SecurityContext.class).isLoggedIn()) { - prepareForLogout(); Beans.getReference(SecurityContext.class).logout(); } } @@ -116,20 +179,4 @@ public abstract class AbstractHTTPAuthorizationFilter implements Filter { response.setContentType("text/plain"); response.getWriter().write(cause.getMessage()); } - - protected static String extractCredentials(String type, String authHeader) throws InvalidCredentialsException { - String result = null; - - if (!Strings.isEmpty(type) && !Strings.isEmpty(authHeader)) { - String regexp = "^" + type + "[ \\n]+(.+)$"; - Pattern pattern = Pattern.compile(regexp); - Matcher matcher = pattern.matcher(authHeader); - - if (matcher.matches()) { - result = matcher.group(1); - } - } - - return result; - } } diff --git a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/BasicAuthFilter.java b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/BasicAuthFilter.java index 417395c..08c860b 100644 --- a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/BasicAuthFilter.java +++ b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/BasicAuthFilter.java @@ -36,37 +36,36 @@ */ package br.gov.frameworkdemoiselle.security; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.apache.commons.codec.binary.Base64; import br.gov.frameworkdemoiselle.util.Beans; -import br.gov.frameworkdemoiselle.util.Strings; public class BasicAuthFilter extends AbstractHTTPAuthorizationFilter { private String credentials; @Override - protected boolean isSupported(String authHeader) { - credentials = extractCredentials("Basic", authHeader); - return !Strings.isEmpty(credentials); + protected String getType() { + return "Basic"; } @Override - protected boolean isActive(RESTSecurityConfig config) { - return config.isBasicFilterActive(); + protected boolean isActive() { + return Beans.getReference(RESTSecurityConfig.class).isBasicFilterActive(); } @Override - protected void prepareForLogin() { + protected void performLogin(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { String[] basicCredentials = getCredentials(credentials); Credentials credentials = Beans.getReference(Credentials.class); credentials.setUsername(basicCredentials[0]); credentials.setPassword(basicCredentials[1]); - } - @Override - protected void prepareForLogout() { + super.performLogin(httpRequest, httpResponse); } private static String[] getCredentials(String header) throws InvalidCredentialsException { diff --git a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/Token.java b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/Token.java index b108263..3a676e6 100644 --- a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/Token.java +++ b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/Token.java @@ -2,8 +2,6 @@ package br.gov.frameworkdemoiselle.security; import javax.enterprise.context.RequestScoped; -import br.gov.frameworkdemoiselle.util.Strings; - @RequestScoped public class Token { @@ -16,8 +14,12 @@ public class Token { public void setValue(String value) { this.value = value; } - + public boolean isEmpty() { - return Strings.isEmpty(value); + return this.value == null; + } + + public void clear() { + this.value = null; } } diff --git a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/TokenAuthFilter.java b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/TokenAuthFilter.java index 8b6c35e..9809bb7 100644 --- a/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/TokenAuthFilter.java +++ b/impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/security/TokenAuthFilter.java @@ -36,29 +36,55 @@ */ package br.gov.frameworkdemoiselle.security; +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import br.gov.frameworkdemoiselle.util.Beans; -import br.gov.frameworkdemoiselle.util.Strings; public class TokenAuthFilter extends AbstractHTTPAuthorizationFilter { - private String token; - - protected boolean isSupported(String authHeader) { - token = extractCredentials("Token", authHeader); - return !Strings.isEmpty(token); + @Override + protected String getType() { + return "Token"; } @Override - protected boolean isActive(RESTSecurityConfig config) { - return config.isTokenFilterActive(); + protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + String authData = getAuthData(request); + + super.doFilter(request, response, chain); + + String value = Beans.getReference(Token.class).getValue(); + if (value != null && !value.equals(authData)) { + response.setHeader("Set-Token", value); + } } @Override - protected void prepareForLogin() { - Beans.getReference(Token.class).setValue(token); + protected boolean isActive() { + return Beans.getReference(RESTSecurityConfig.class).isTokenFilterActive(); } @Override - protected void prepareForLogout() { + protected void performLogin(HttpServletRequest request, HttpServletResponse response) { + Token token = Beans.getReference(Token.class); + String authData = getAuthData(request); + token.setValue(authData); + + super.performLogin(request, response); } + + // public void setHeader(@Observes AfterLoginSuccessful event) { + // Token token = Beans.getReference(Token.class); + // + // if (!token.isEmpty()) { + // HttpServletResponse response = Beans.getReference(HttpServletResponse.class); + // response.setHeader("Set-Token", token.getValue()); + // } + // } } -- libgit2 0.21.2