Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

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,