Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

Colocar 2 ou mais perfils com granted authory

Eu estou fazendo um projeto meu para testar meus conhecimentos, e nesse caso estou fazendo com 3 entidades sendo UserDetails, e estou usando permissão com o HasRole, quando eu faço a autorização com token funciona com as 3 entidades. ao fazer uma consulta com o usuario logado de motorista por causa da entidade Responsavel Estar com Eager em perfils, ele joga uma exception de No value is Present, Por causa do Optional, , tentei trocar de Eager para Lazy no relacionamento ManyToMany mas me devolve uma lazy exception, Estou pensando em fazer Um Join fetch mas queria saber se tem outra opção.

resumo: ao Fazer um endpoint com usuario Logado a Outra entidade gera problema, mas se estou logado na entidade que está com o EAGER ela funciona normalmente, espero que tenha entendido kkk vou mandar o codigo aqui

estou usando Lombok

public class Motorista implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nome;
private String cpf;
private String cnh;
private String telefone;
private Date dataDeNascimento;

private String senha;

private String email;
@ManyToMany
private List<Perfil> perfils = new ArrayList<>();
@OneToMany(mappedBy = "motorista", fetch = FetchType.LAZY)
private List<Automovel> automovel = new ArrayList<>();

@JsonIgnore
@OneToOne(fetch = FetchType.LAZY)
private ContaSalario contaSalario;

@JsonIgnore
@ManyToMany
private List<ParceiroMotorista> parceiroMotorista = new ArrayList<>();

@OneToMany(mappedBy = "motorista", fetch = FetchType.LAZY)
private List<Responsavel> responsavel = new ArrayList<>();


public Motorista(String nome, String cpf, String cnh, String telefone, Date dataDeNascimento, String senha, String email) {
    this.nome = nome;
    this.cpf = cpf;
    this.cnh = cnh;
    this.telefone = telefone;
    this.dataDeNascimento = dataDeNascimento;
    this.senha = senha;
    this.email = email;
}

public Motorista() {
}

public Motorista(String nome, String telefone, Date dataDeNascimento, List<ParceiroMotorista> parceiroMotorista) {
    this.nome = nome;
    this.telefone = telefone;
    this.dataDeNascimento = dataDeNascimento;
    this.parceiroMotorista = parceiroMotorista;
}


public void adicionarAutomovel(Automovel automovel) {

    automovel.setMotorista(this);
    this.automovel.add(automovel);
}

public void adicionar(ParceiroMotorista parceiroMotorista) {
    List<Motorista> motorista = new ArrayList<>();

    parceiroMotorista.setMotorista(motorista);
    this.parceiroMotorista.add(parceiroMotorista); //adiciona na tabela do relacionamento many to many


}


@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return perfils;
}

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

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

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

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

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

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

}

10 respostas

@Entity @Getter @Setter @Transactional public class Perfil implements GrantedAuthority {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String nome;
@JsonIgnore
@ManyToMany(mappedBy = "perfils", cascade = CascadeType.ALL)
private List<Motorista> motoristas = new ArrayList<>();
@JsonIgnore
@ManyToMany(mappedBy = "perfils", cascade = CascadeType.ALL)
private List<ParceiroMotorista> parceiroMotoristas = new ArrayList<>();
@JsonIgnore
@ManyToMany(mappedBy = "perfils", cascade = CascadeType.ALL)
private List<Responsavel> responsavel = new ArrayList<>();

@Override
public String getAuthority() {
    return nome;
}

}

@Entity @Getter @Setter @EqualsAndHashCode public class Responsavel implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nome;
private Date dataNascimento;
private String cpf;
private String telefone;
private String senha ;

private String email;
@Enumerated(EnumType.STRING)
private  EstadoCivil estadoCivil ;
@JsonIgnore
@ManyToOne
private Motorista motorista;

@ManyToMany (fetch = FetchType.EAGER)
private List<Perfil> perfils = new ArrayList<>();

@ManyToMany
private List<Aluno> aluno = new ArrayList<>();


public Responsavel() {
}

public Responsavel(String nome, Date dataNascimento, String cpf, String telefone, String senha, String email, EstadoCivil estadoCivil) {
    this.nome = nome;
    this.dataNascimento = dataNascimento;
    this.cpf = cpf;
    this.telefone = telefone;
    this.senha = senha;
    this.email = email;
    this.estadoCivil = estadoCivil;
}

public  void adicionar (Aluno aluno){

    List<Responsavel> responsavel = new ArrayList<>();

    aluno.setResponsavel(responsavel);
    this.aluno.add(aluno);
}


@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return perfils;
}

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

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

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

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

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

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

}

public class ParceiroMotorista implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nome;
private String telefone;
private Date dataNascimento;
private String cpf;
private String senha;

private String email;

@ManyToMany
private List<Perfil> perfils = new ArrayList<>();
@JsonIgnore
@ManyToMany(targetEntity = Motorista.class, mappedBy = "parceiroMotorista", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Motorista> motorista = new ArrayList<>();


    public ParceiroMotorista(String nome, String telefone, Date dataNascimento, String cpf,String email, String senha) {
        this.nome = nome;
        this.telefone = telefone;
        this.dataNascimento = dataNascimento;
        this.cpf = cpf;
        this.email= email;
        this.senha = senha;
    }

public ParceiroMotorista(String nome, String telefone) {
    this.nome = nome;
    this.telefone = telefone;
}

public ParceiroMotorista() {
}

public void adicionar(Motorista motorista) {
    List<ParceiroMotorista> parceiroMotorista = new ArrayList<>();

    motorista.setParceiroMotorista(parceiroMotorista);
    this.motorista.add(motorista);

}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return perfils;
}

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

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

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

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

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

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

}

@EnableWebSecurity @Configuration public class SecutiryConfigurations {

@Autowired
private TokenServiceResponsavel tokenServiceResponsavel;
@Autowired
private ResponsavelRepository responsavelRepository;
@Autowired
private TokenServiceMotorista tokenServiceMotorista;
@Autowired
private MotoristaRepository motoristaRepository;
@Autowired
private ParceiroMotoristaRepository parceiroMotoristaRepository;
@Autowired
private TokenServiceParceiroMotorista tokenServiceParceiroMotorista;

@Bean //geração do bCrypt
protected PasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
}


@Bean //configuração autenticação
@Transactional
protected AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
}

@Bean //controle acesso, de perfil
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.authorizeHttpRequests() //autorização de metodos
            .antMatchers(HttpMethod.POST, "/responsavel").permitAll()
            .antMatchers(HttpMethod.POST, "/parceiroMotorista").permitAll()
            .antMatchers(HttpMethod.POST, "/motorista").permitAll()
            .antMatchers(HttpMethod.GET, "/actuator/**").permitAll() //MUDAR pois actuator devolve informações sensiveis da aplicação,
            .antMatchers(HttpMethod.POST, "/auth/**").permitAll()
            .antMatchers(HttpMethod.GET, "/swagger-ui/**").permitAll()
            .antMatchers(HttpMethod.PUT, "/responsavel/*").hasRole("RESPONSAVEL")
            .antMatchers(HttpMethod.POST, "/responsavel/aluno/*").hasRole("RESPONSAVEL")
            .antMatchers(HttpMethod.PUT, "/responsavel/aluno/*").hasRole("RESPONSAVEL")
            .antMatchers(HttpMethod.GET, "/motorista/*").hasRole("RESPONSAVEL")
            .antMatchers(HttpMethod.PUT, "/motorista/*").hasRole("MOTORISTA")
            .anyRequest().authenticated() //qualquer outra requeste, precisa estar autenticado,
            .and().csrf().disable() //csrf protecao contra hackers, nao necessario pelos tokens,
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //politica da api, statelles,
            .and().addFilterBefore(new AutenticacaoViaToken(responsavelRepository, tokenServiceResponsavel,
                            tokenServiceMotorista,
                            motoristaRepository,
                            parceiroMotoristaRepository, tokenServiceParceiroMotorista),
                    UsernamePasswordAuthenticationFilter.class);

    return httpSecurity.build();
}

@Bean //configurações de recursos estaticos (imagens, etc.)
public WebSecurityCustomizer webSecurityCustomizer() {
    return (web) -> web.ignoring().antMatchers("/**.html", "/v2/api-docs", "/webjars/**", "/configuration/**", "/swagger-resources/**");
}

/*public static void main(String[] args) {
    System.out.println(new BCryptPasswordEncoder().encode("123456"));
}

*/ }

Acredito que quando ele para nessa classe aqui ele joga a exception

@Service public class AutenticacoService implements UserDetailsService {

@Autowired
private ResponsavelRepository responsavelRepository;

@Autowired
private MotoristaRepository motoristaRepository;

@Autowired
private ParceiroMotoristaRepository parceiroMotoristaRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {


    Optional<Motorista> motorista = motoristaRepository.findByEmail(username);
    Optional<Responsavel> responsavel = responsavelRepository.findByEmail(username);
    Optional<ParceiroMotorista> parceiroMotorista = parceiroMotoristaRepository.findByEmail(username);


    if (motorista.isPresent()) {
        return motorista.get();
    } else if (parceiroMotorista.isPresent()) {
        return parceiroMotorista.get();
    }
    if (responsavel.isPresent()) {
        return responsavel.get();
    } else {
        throw new UsernameNotFoundException("dados invalidos");
    }
}

2022-07-15 10:29:59.383 ERROR 10000 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

o Erro:

java.util.NoSuchElementException: No value present at java.base/java.util.Optional.get(Optional.java:143) ~[na:na] at com.van.vanescolarprojeto.controler.secutiry.AutenticacaoViaToken.autenticarResponsavel(AutenticacaoViaToken.java:77) ~[classes/:na] at com.van.vanescolarprojeto.controler.secutiry.AutenticacaoViaToken.doFilterInternal(AutenticacaoViaToken.java:89) ~[classes/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar:5.3.21] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.7.2.jar:5.7.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar:5.3.21]

@RestController @RequestMapping("/auth") public class AutenticacaoController { @Autowired private TokenServiceResponsavel tokenServiceResponsavel; @Autowired private TokenServiceMotorista tokenServiceMotorista; @Autowired private TokenServiceParceiroMotorista tokenServiceParceiroMotorista; @Autowired private AuthenticationManager authenticationManager;

@PostMapping("/responsavel")
public ResponseEntity<TokenDto> autenticarResponsavel(@RequestBody LoginForm form) {
    UsernamePasswordAuthenticationToken dadosLogin = form.converter();
    try {
        Authentication authentication = authenticationManager.authenticate(dadosLogin);
        String token = tokenServiceResponsavel.gerarTokenResponsavel(authentication);

        return ResponseEntity.ok(new TokenDto(token, "Bearer"));
    } catch (AuthenticationException e) {
        e.printStackTrace();
     return  ResponseEntity.badRequest().build();
    }
}

@PostMapping("/motorista")
public ResponseEntity<TokenDto> autenticarMotorista(@RequestBody LoginForm form) {
    UsernamePasswordAuthenticationToken dadosLogin = form.converter();
    try {
        Authentication authenticate = authenticationManager.authenticate(dadosLogin);
        String token = tokenServiceMotorista.gerarTokenMotorista(authenticate);
        return ResponseEntity.ok(new TokenDto(token, "Bearer"));
    } catch (AuthenticationException e) {
        e.printStackTrace();
      return  ResponseEntity.badRequest().build();
    }

}

   @PostMapping("/parceiro")
public ResponseEntity<TokenDto> autenticarParceiro(@RequestBody LoginForm form) {
    UsernamePasswordAuthenticationToken dadosLogin = form.converter();
    try {
        Authentication authenticate = authenticationManager.authenticate(dadosLogin);
        String token = tokenServiceParceiroMotorista.gerarTokenParceiro(authenticate);
        return ResponseEntity.ok(new TokenDto(token, "Bearer"));
    } catch (AuthenticationException e) {
        e.printStackTrace();
        return  ResponseEntity.badRequest().build();
    }
}

Oi Rodrigo,

Nesse tipo de situação o recomendado é utilizar herança nos mapeamentos:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Usuario  implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String email;
    private String senha;

    //outros atributos COMUNS para TODAS as entidades filhas...

    @ManyToMany(fetch = FetchType.EAGER)
    private List<Perfil> perfis = new ArrayList<>();

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return perfis;
    }

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

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

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

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

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

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

}
@Entity
public class Perfil implements GrantedAuthority {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nome;

    @Override
    public String getAuthority() {
        return nome;
    }

}
@Entity
public class Motorista extends Usuario {

    //atributos EXCLUSIVOS de Motorista

}
@Entity
public class Responsavel extends Usuario {

    //atributos EXCLUSIVOS de Responsavel

}
@Entity
public class ParceiroMotorista extends Usuario {

    //atributos EXCLUSIVOS de ParceiroMotorista

}

nossa que interressante vou tentar aqui, obrigado

solução!

funcionou! muito obrigado,