Rules processing with spring security

Asked

Viewed 234 times

0

I am building an application with Spring Security and after performing all settings to have the custom login done with the UserDetailsService, I realized that when logging in, although the data is recognized and the user is authenticated, the instructions on Thymeleaf as, for example, sec:authorize="hasRole('ADMINISTRADOR')" are not recognised. On the other hand sec:authorize="isAnonymous()" is recognized and processed normally. Someone can tell me if there is something wrong with this code that prevents my view from processing the rules?

Gpuserdetailsservice:

    import static br.com.dev.util.JdbcUtils.*;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.sql.DataSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;

    @Component
    public class GpUserDetailsService implements UserDetailsService {

        private static final Logger logger = Logger.getLogger(GpUserDetailsService.class.getSimpleName());

        @Autowired
        private DataSource dataSource;

        @Override
        public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
            Connection connection = null;

            try {
                connection = dataSource.getConnection();

                GpUserDetails userDetails = buscarUsuario(connection, login);

                Collection<GrantedAuthority> permissoesPorUsuario = buscarPermissoes(connection,
                        login, PERMISSOES_POR_USUARIO);

    //            Collection<GrantedAuthority> permissoesPorGrupo = buscarPermissoes(connection,
    //                    login, PERMISSOES_POR_GRUPO);

                userDetails.getAuthorities().addAll(permissoesPorUsuario);
    //            userDetails.getAuthorities().addAll(permissoesPorGrupo);

                return userDetails;
            } catch (Exception e) {
                logger.log(Level.SEVERE, "Problemas com a tentativa de conexão!", e);
                throw new UsernameNotFoundException("Problemas com a tentativa de conexão!", e);
            } finally {
                try {
                    if (connection != null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    logger.log(Level.SEVERE, "Problemas ao tentar fechar a conexão!", e);
                    throw new UsernameNotFoundException("Problemas ao tentar fechar a conexão!", e);
                }
            }
        }

        public GpUserDetails buscarUsuario(Connection connection, String login) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(USUARIO_POR_LOGIN);
            ps.setString(1, login);

            ResultSet rs = ps.executeQuery();

            if (!rs.next()) {
                throw new UsernameNotFoundException("Usuário " + login + " não encontrado!");
            }

            String nomeUsuario = rs.getString("nome_usuario");
            String emailUsuario = rs.getString("email_usuario");
            String dataNascimentoUsuario = rs.getString("data_nascimento_usuario");
            String telefoneUsuario = rs.getString("telefone_usuario");
            String sexoUsuario = rs.getString("sexo_usuario");
            String senhaUsuario = rs.getString("senha_usuario");
            boolean statusUsuario = rs.getBoolean("status_usuario");

            rs.close();
            ps.close();

            return new GpUserDetails(nomeUsuario, emailUsuario, dataNascimentoUsuario, telefoneUsuario, sexoUsuario, senhaUsuario, statusUsuario);
        }

        public Collection<GrantedAuthority> buscarPermissoes(Connection connection, String login, String sql) throws SQLException {
            List<GrantedAuthority> permissoes = new ArrayList<>();

            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setString(1, login);

            ResultSet rs = ps.executeQuery();

            while (rs.next()) {
                permissoes.add(new SimpleGrantedAuthority(rs.getString("nome_permissao")));
            }

            rs.close();
            ps.close();

            return permissoes;
        }
    }

Gpuserdetails:

package br.com.dev.security;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class GpUserDetails implements UserDetails {

    private static final long serialVersionUID = 1L;

    private String nomeUsuario;
    private String emailUsuario;
    private String dataNascimentoUsuario;
    private String telefoneUsuario;
    private String sexoUsuario;
    private String senhaUsuario;
    private boolean statusUsuario;
    private Collection<GrantedAuthority> permissoes = new ArrayList<>();

    public GpUserDetails(String nomeUsuario, String emailUsuario, String dataNascimentoUsuario, String telefoneUsuario, String sexoUsuario, String senhaUsuario, boolean statusUsuario) {
        this.nomeUsuario = nomeUsuario;
        this.emailUsuario = emailUsuario;
        this.dataNascimentoUsuario = dataNascimentoUsuario;
        this.telefoneUsuario = telefoneUsuario;
        this.sexoUsuario = sexoUsuario;
        this.senhaUsuario = senhaUsuario;
        this.statusUsuario = statusUsuario;
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return permissoes;
    }

    public String getNomeUsuario(){
        return nomeUsuario;
    }

    public String getDataNascimentoUsuario() {
        return dataNascimentoUsuario;
    }

    public String getTelefoneUsuario() {
        return telefoneUsuario;
    }

    public String getSexoUsuario() {
        return sexoUsuario;
    }

    @Override
    public String getPassword() {
        return senhaUsuario;
    }

    @Override
    public String getUsername() {
        return emailUsuario;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return statusUsuario;
    }
}

User:

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.security.core.GrantedAuthority;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

@Entity
@Table(name = "usuario")
public class Usuario implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long idUsuario;

    @NotBlank(message = "O nome não pode ser vazio.")
    @NotNull(message = "O nome não pode ser nulo.")
    @Column(name = "nomeUsuario")
    private String nomeUsuario;

    @NotBlank(message = "O e-mail não pode ser vazio.")
    @NotNull(message = "O e-mail não pode ser nulo.")
    @Column(name = "emailUsuario")
    private String emailUsuario;

    @NotBlank(message = "A data de nascimento não pode ser vazia.")
    @NotNull(message = "A data de nascimento não pode ser nula.")
    @Column(name = "dataNascimentoUsuario")
    private String dataNascimentoUsuario;

    @NotBlank(message = "Pelo menos um telefone deve ser inserido.")
    @NotNull(message = "Pelo menos um telefone deve ser inserido.")
    @Column(name = "telefoneUsuario")
    private String telefoneUsuario;

    @NotBlank(message = "O sexo não pode ser vazio.")
    @Size(min = 1, max = 1, message = "O sexo deve ser preenchido com M, F ou N.")
    @NotNull(message = "O sexo não pode ser vazio.")
    @Column(name = "sexoUsuario")
    private String sexoUsuario;

    @NotBlank(message = "A senha não pode ser vazia.")
    @Size(min = 8, message = "A senha deve ter no mínimo 8 digitos.")
    @NotNull(message = "A senha não pode ser vazia.")
    @Column(name = "senhaUsuario")
    private String senhaUsuario;

    @Column
    @NotNull
    private boolean statusUsuario;

    @ManyToOne
    @JoinColumn(name = "tipoUsuario_fk")
    private TipoUsuario tipoUsuario;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "usuario_permissao",
            joinColumns = @JoinColumn(name = "usuario_fk"),
            inverseJoinColumns = @JoinColumn(name = "permissao_fk")
    )
    private List<Permissao> permissoes;

    public Usuario(String nomeUsuario, String emailUsuario, String dataNascimentoUsuario, String telefone, String sexoUsuario, String senhaUsuario, TipoUsuario tipoUsuario) {
        this.nomeUsuario = nomeUsuario;
        this.emailUsuario = emailUsuario;
        this.dataNascimentoUsuario = dataNascimentoUsuario;
        this.telefoneUsuario = telefone;
        this.sexoUsuario = sexoUsuario;
        this.senhaUsuario = senhaUsuario;
        this.tipoUsuario = tipoUsuario;
        this.statusUsuario = true;
    }

    public Usuario() {
    }

    public long getIdUsuario() {
        return idUsuario;
    }

    public void setIdUsuario(long idUsuario) {
        this.idUsuario = idUsuario;
    }

    public String getNomeUsuario() {
        return nomeUsuario;
    }

    public void setNomeUsuario(String nomeUsuario) {
        this.nomeUsuario = nomeUsuario;
    }

    public String getEmailUsuario() {
        return emailUsuario;
    }

    public void setEmailUsuario(String emailUsuario) {
        this.emailUsuario = emailUsuario;
    }

    public String getDataNascimentoUsuario() {
        return dataNascimentoUsuario;
    }

    public void setDataNascimentoUsuario(String dataNascimentoUsuario) {
        this.dataNascimentoUsuario = dataNascimentoUsuario;
    }

    public String getTelefoneUsuario() {
        return telefoneUsuario;
    }

    public void setTelefoneUsuario(String telefone) {
        this.telefoneUsuario = telefone;
    }

    public String getSexoUsuario() {
        return sexoUsuario;
    }

    public void setSexoUsuario(String sexoUsuario) {
        this.sexoUsuario = sexoUsuario;
    }

    public String getSenhaUsuario() {
        return senhaUsuario;
    }

    public void setSenhaUsuario(String senhaUsuario) {
        this.senhaUsuario = senhaUsuario;
    }

    public TipoUsuario getTipoUsuario() {
        return tipoUsuario;
    }

    public void setTipoUsuario(TipoUsuario tipoUsuario) {
        this.tipoUsuario = tipoUsuario;
    }

    public boolean isStatusUsuario() {
        return statusUsuario;
    }

    public void setStatusUsuario(boolean statusUsuario) {
        this.statusUsuario = statusUsuario;
    }

    public List<Permissao> getPermissoes() {
        return permissoes;
    }

    public void setPermissoes(List<Permissao> permissoes) {
        this.permissoes = permissoes;
    }
}

Jdbcsecurityconfig:

import static br.com.dev.util.JdbcUtils.*;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@Profile("JDBC")
public class JdbcSecurityConfig {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
        builder
                .jdbcAuthentication()
                .usersByUsernameQuery(USUARIO_POR_LOGIN)
                .authoritiesByUsernameQuery(PERMISSOES_POR_USUARIO);
//                .groupAuthoritiesByUsername(PERMISSOES_POR_GRUPO);
    }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.dev</groupId>
    <artifactId>ajudaf</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--Aqui foi declarada a versão do spring e, portanto, as dependencias não precisam-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>
    <!--Fim-->

    <properties>
        <java.version>1.8</java.version>

    </properties>

    <dependencies>

        <!--Dependências padrão para o Spring. (O starter garante um pacote com tudo que precisamos, sem aquele monte de importações)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
        </dependency>
        <!--Fim-->

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--Plugin para comunicação do spring com o maven-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--Fim-->
        </plugins>
    </build>
</project>
  • I can use when configuring users by memory, but when I do with direct authentication in the database it does not process. What puzzles me is that if I make one: <span sec:authentication="principal.authorities"></span> and <span sec:authentication="name"></span>, I get the name and rule, but it is not recognized by Authorize

  • In the database the role is written this way, ROLE_ADMINISTRATOR ?

1 answer

-1

Try adding the ROLE prefix_

sec:authorize="hasRole('ROLE_ADMINISTRADOR')" Returns true if the current principal has the function specified. By default, if the given function does not start withROLE_, it will be added. This can be customized by modifying the defaultRolePrefix in the DefaultWebSecurityExpressionHandler.

But you can use hasAuthority sec:authorize="hasAuthority('ADMINISTRADOR')

Update from Spring Security 3.x to 4.x. Changes hasRole() to hasAuthority(). http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-common-built-in

Browser other questions tagged

You are not signed in. Login or sign up in order to post.