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…
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:
</http>
<!-- Criação de alias para o seu provedor de autenticação -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>
<!-- Definicao do bean que irá receber as conexões e avaliar se o usuário tem ou não permissão para acesso -->
<beans:bean name="myAuthenticationProvider"
class="br.com.meuprojeto.security.MyAuthenticationProvider">
</beans:bean>
<beans:bean id="passwordEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<beans:constructor-arg index="0" value="256" />
</beans:bean>
[/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<String> rolesForThisClient = clientService.findAllRoles(client);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
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.
- <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”…
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"))