I'm having problems with user permissions using Spring Security. Signing the user assigns him the permission that is due to him, however when accessing the system the option in the menu that the user would have access does not appear.
Here's how Spring Security is configured on my system:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Autowired
IUsuarioDAO usuarioDAO;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(usuarioDAO)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/vendas/cadastro-vendas").hasAnyRole("VENDAS_MERCADO")
.anyRequest().authenticated()
.and().formLogin().loginPage("/index").permitAll()
.failureUrl("/index?error=true").defaultSuccessUrl("/home", true).permitAll()
.and().rememberMe().userDetailsService(usuarioDAO)
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
My User Entity:
package br.com.mercadinhojt.mercado.models;
import java.util.ArrayList;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class UsuarioDetails implements UserDetails{
private static final long serialVersionUID = 1L;
private String nome;
private String login;
private String senha;
private boolean ativo;
private Collection<GrantedAuthority> permissoes = new ArrayList<>();
public UsuarioDetails(String nome, String login, String senha, boolean ativo) {
this.nome = nome;
this.login = login;
this.senha = senha;
this.ativo = ativo;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return permissoes;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return this.senha;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return this.login;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return this.ativo;
}
}
My DAO Class
public class UsuarioDAOImpl implements IUsuarioDAO, UserDetailsService{
private static final Logger logger = Logger.getLogger(UsuarioDetails.class.getSimpleName());
private JdbcTemplate jdbcTemplate;
private Connection connection;
private CallableStatement cs;
private ResultSet rs;
@Autowired
public UsuarioDAOImpl(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UsuarioDetails userDetails = null;
try {
connection = jdbcTemplate.getDataSource().getConnection();
userDetails = buscarUsuario(connection, username);
Collection<GrantedAuthority> permissoesPorUsuario = buscarPermissoes(connection,username);
userDetails.getAuthorities().addAll(permissoesPorUsuario);
return userDetails;
} catch (UsernameNotFoundException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}finally{
try {
connection.close();
cs.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return userDetails;
}
public UsuarioDetails buscarUsuario(Connection connection, String login) throws SQLException {
cs = this.connection.prepareCall("{call MEJT_SP_SEL_USUARIOS(?,?)}");
cs.setString("MODO", "BUSCAR_USUARIO");
cs.setString("LOGIN_USER", login);
rs = cs.executeQuery();
String nome = null;
String senha = null;
boolean ativo = false;
while(rs.next()){
nome = rs.getString("NOME");
senha = rs.getString("SENHA");
ativo = rs.getBoolean("ATIVO");
}
rs.close();
cs.close();
return new UsuarioDetails(nome, login, senha, ativo);
}
public Collection<GrantedAuthority> buscarPermissoes(Connection connection, String login) throws SQLException {
List<GrantedAuthority> permissoes = new ArrayList<>();
cs = this.connection.prepareCall("{call MEJT_SP_SEL_USUARIOS(?,?)}");
cs.setString("MODO", "ACESSAR_APLICACAO");
cs.setString("LOGIN_USER", login);
rs = cs.executeQuery();
while (rs.next()) {
permissoes.add(new SimpleGrantedAuthority(rs.getString("NMFORMULARIO")));
}
rs.close();
cs.close();
return permissoes;
}
}
NMFORMULARIO would be the name of my ROLE . When the user logs in to the system I get the user's data and then I get all the permissions that this user has access to.
By debugging the system the SearchPermissions () method is correctly picking up the permission that the user has.
InmyJSPHeaderIamleavingthemenu(specificallytheaccessthatthisroleallows):
<sec:authorizeaccess="hasAnyRole('VENDAS_MERCADO')">
<li class="nav-item">
<a class="nav-link" href="${s:mvcUrl('VC#vendasCaixa').build()}">Caixa</a>
</li>
</sec:authorize>
To build this rule I used an AlgaWorks class as a base, but they used spring bot. But the way I rode it is very much like what they were teaching, but it is not working. When I access my application this menu item is not available to the user. This application I'm creating is my CBT project and this question of attributions of each user would be one of the fundamentals of my application and I can not make that access rule work. And I also did not want all registered users on the system to have access to everything in the application.
I would like to know if there is anything wrong with recognizing the user's permission.
If you can contribute, I would appreciate it a lot, this is just missing to complete my project