[RESOLVIDO] Spring Security - Atualizar Authorities / Permissões

Olá Pessoal!
Recentemente implementamos a segurança de um sistema (JSF + Primefaces) utilizando o spring security…
O sistema está funcionando perfeitamente, porém quando fazemos atualização de alguma ROLE/Permissões do usuário, até onde percebemos, o spring não interpreta está alteração em tempo de execução…
Diante do exposto pergunto-lhes…
Temos como fazer com que o spring atualize sua SQL / regras em tempo de execução ? Desta forma quando o usuário efetuasse a próxima requisição no servidor ele faria o Refresh das permissões…

Desde já agradeço.
:slight_smile: :slight_smile:

Primeiramente qual a configuração que você esta usando?
Me antecipando eu sugiro a seguinte configuração para o seu Spring Security, desta forma você tem o controle da validação e assim fica mais facil customizar sem depender do comportamento padrão do Spring, segue:

[code]
<http use-expressions=“true” auto-config=“false” disable-url-rewriting=“true”>
<session-management session-fixation-protection=“migrateSession” />
<intercept-url pattern="/lista-produtos/*" access=“hasRole(‘ROLE_USER’)” />
<intercept-url pattern="/admin/" access=“hasRole(‘ROLE_ADMIN’)” />
<intercept-url pattern="/j_spring_security_check" />
<intercept-url pattern="/
" requires-channel=“http” />

     &lt;/http&gt;

       &lt;!-- Criação de alias para o seu provedor de autenticação --&gt;
       &lt;authentication-manager alias="authenticationManager"&gt;
			                     &lt;authentication-provider ref="myAuthenticationProvider" /&gt;
   		     &lt;/authentication-manager&gt;

        &lt;!-- Definicao do bean que irá receber as conexões e avaliar se o usuário tem ou não permissão para acesso --&gt;
    	         &lt;beans:bean name="myAuthenticationProvider"
			                      class="br.com.meuprojeto.security.MyAuthenticationProvider"&gt;
    	         &lt;/beans:bean&gt;
	
     	         &lt;beans:bean id="passwordEncoder"
			                     class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"&gt;
			                    &lt;beans:constructor-arg index="0" value="256" /&gt;
      	         &lt;/beans:bean&gt;
[/code]

Após esta configuração do contexto você pode fazer a implementação do seu provider, que seria algo assim:

@Component
public class MyAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

	@Autowired
	private ClientService clientService;

	
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication)
					throws AuthenticationException {
	}

	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) {
		String password = (String) authentication.getCredentials();
		
                if (!StringUtils.hasText(password)) {
			throw new BadCredentialsException("Entre com a senha por favor");
		}

		Client client = this.clientService.findByUsenameAndPassword(new Client(username, password));

		if (this.client == null) {
			throw new BadCredentialsException("Usuário invalido!");
		}

		authentication.setDetails(client);

                List&lt;String&gt; rolesForThisClient = clientService.findAllRoles(client); 
              
                List&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;GrantedAuthority&gt;();

                foreach(String role in rolesForThisClient) {
                     authorities.add(new GrantedAuthorityImpl(role));
                }
		

		return new User(username, password, true, true, true, true, authorities);
	}
}

É isso ai, se você enviar suas configurações ficará mais facil encontrar uma solução.

abraço!

Olá mmaico,
Hoje está com a seguinte config:

- <b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http auto-config="true" access-denied-page="/publico/acessoNegado.xhtml">
  <intercept-url pattern="/restrito/**" access="ROLE_TESTE" /> 
  <form-login login-page="/publico/login.xhtml" always-use-default-target="true" default-target-url="/restrito/index.xhtml" authentication-failure-url="/publico/index.xhtml?login_error=1" /> 
  <logout invalidate-session="true" /> 
  <remember-me /> 
  </http>
<authentication-manager>
<authentication-provider>
  <jdbc-user-service data-source-ref="financeiroDataSource" 

authorities-by-username-query="SELECT login, role FROM permissoes where login=?;" 

users-by-username-query="SELECT login, senha, status FROM login where login = ?" /> 
  </authentication-provider>
  </authentication-manager>
  </b:beans>

Você acha que se alterar o contexto para seu exemplo ele ira atualizar as permissões em tempo de execução ? Queremos que as modificações efetuadas no perfil reflitam a medida que o perfil de acesso for “atualizado”…

Abs.

Olá,
Tanto a sua abordagem quando a minha terá o mesmo efeito, só muda a forma.
O Spring Security irá executar essa rotina somente uma vez, que é quando o usuário se autentica no sistema, após isso ele não irá mais chamar sua rotina no DB, nem o provider no meu exemplo.

Quando você altera as pemissões do usuário isso só será refletido no próximo login.

Pelo que persebi o próximo login do usuário não é o suficiente, então o que se pode fazer é o seguinte:

1 - Crie um interceptor que irá atuar em /* menos a uri de login, ou seja todas as requisições.
2 - Para cada requisição veja no banco se houve ateração(select qualquer coisa), use SecurityContextHolder.getContext().getPrincipal() para saber quem é o usuário da requisição.
3 - Use no metodo do seu interceptor SecurityContextHolder.getContext().getAuthorities().add(new GrantedAuthorityImpl("NovaRoleQueFoiAdicionada"))
4 - Para remove segue o mesmo esquema SecurityContextHolder.getContext().getAuthorities().remove(new GrantedAuthorityImpl("RoleQueFoiRemovida"))    

Espero ter ajudado.

Abraço!

Olá Mmaico

Achei que o Spring tivesse “nativo” esta configuração, mas tentarei implementar sua solcuação…

Muito Obrigado pela ajuda, Resolvido!