Spring Security Login Problem

freebeer

Mitglied
Guten Abend,

Ich möchte Spring Security in meine Anwedung integrieren. Leider komme ich aber gerde nicht weiter. Ich möchte den User auf eine Custom-Login Page leiten von der aus er/sie/es sich anmelden kann. Standard Prozedur. Ich komme bis zur Login Page, danach passiert aber nichts weiter, ich gebe die Benutzerdaten eines Benutzers an der in der Datenbank liegt und werde einfach direkt wieder auf die Login Seite geleitet. Das Login Template ist ein Standard Thymleaf Template. Jetzt muss ich einfach mal blöd fragen, Habe ich etwas falsch konfiguriert? Also scheinbar ja, ich komme aber leider einfach nicht darauf was. Vielleicht könnt ihr mir ja behilflich sein


Java:
@Configuration
public class SpringSecurityConfig {

      private final CustomUserDetailsService customUserDetailsService;
      private final CustomAuthenticationSuccessHandler customauthhandler;

    public SpringSecurityConfig(CustomUserDetailsService customUserDetailsService, CustomAuthenticationSuccessHandler customauthhandler) {
        this.customUserDetailsService = customUserDetailsService;
        this.customauthhandler = customauthhandler;
    }

    @Bean
    protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        
        http.csrf(csrf -> csrf.disable()).authorizeHttpRequests((authorize) -> {
            authorize.requestMatchers(publicUrl).permitAll();
            authorize.requestMatchers("/api/").permitAll();
            authorize.requestMatchers("/api/register/save").permitAll();
            authorize.anyRequest().authenticated();
        });
            http.formLogin(form-> form.loginPage("/api/login").permitAll()
    //            .defaultSuccessUrl("/api/"));
                .successHandler(customauthhandler)); 
            return http.build();   
            
    }

    @Bean
    AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        authenticationProvider.setUserDetailsService(customUserDetailsService);
        return authenticationProvider;
    }
    
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

@Service
public class CustomUserDetailsService implements UserDetailsService {

    private UserRepository userRepository;
    
    
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username);
        if(user == null) {
            throw new UsernameNotFoundException("user not found");
        }
        return new CustomUserDetails(user);
    }
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        if(userDetails == null) {
            System.out.println("kein User gefunden");
        }
        String username = userDetails.getUsername();
        System.out.println(username);
        boolean hasjobSeekerRole = authentication.getAuthorities().stream().anyMatch(r->r.getAuthority().equals("ADMIN"));
        boolean hasRecruiterRole = authentication.getAuthorities().stream().anyMatch(r->r.getAuthority().equals("USER"));
        if(hasRecruiterRole || hasjobSeekerRole){
            response.sendRedirect("/api/");
        }
    }
}
}[/CODE]

}[/CODE]
 
Die CustomUserDetails Klasse hast du vergessen zu posten. Hier ist wohl am interessantesten, dass die Rollen des gefundenen Users in eine Collection aufgenommen werden. Wenn das alles klappt, dann solltest du anfangen zu loggen. Mit sout hast du ja schon minimal angefangen und das ist wohl besser als nichts.

Um das Problem zu finden musst du im CustomUserDetailsService anfangen (gefundenen User loggen), dann in CustomUserDetails weitermachen und den CustomAuthenticationSuccessHandler nicht vergessen. Wenn hier die Rollen nicht stimmen, dann wird nicht zu /api/ sondern dahin redirected was im Controller definiert ist. Die Rollen sehen übrigens verdächtig aus (hasjobSeekerRole <--> ADMIN, hasRecruiterRole <--> USER). Wenn das Drittcode ist, den du verändert hast, dann nachsehen, ob in der db Rollen wie JobSeeker oder Recruiter gespeichert sind und das korrigieren (register template). Das zeigt aber auch das Logging.
 
Das wären die CustomUserDetails, das mit den JobSeeker und Recruiter habe ich angepasst, nur vergessen im Code an dieser Stelle umzubenenen.


Java:
public class CustomUserDetails implements UserDetails {

    private static final long serialVersionUID = 1L;
    
    private final User user;
    
    public CustomUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        UserType usersType = user.getUserType();
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(usersType.getUserType()));
        return authorities;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {   
        return user.getEmail();
    }

}
 
Das wären die CustomUserDetails, das mit den JobSeeker und Recruiter habe ich angepasst, nur vergessen im Code an dieser Stelle umzubenenen.


Java:
public class CustomUserDetails implements UserDetails {

    private static final long serialVersionUID = 1L;
  
    private final User user;
  
    public CustomUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        UserType usersType = user.getUserType();
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(usersType.getUserType()));
        return authorities;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() { 
        return user.getEmail();
    }

}
Ich habe es jetzt mit dieser Configuration zum laufen gebracht und zusätzlich das Template rausgeschmissen sieht in Postman ganz gut aus. Allerdings ist jetzt der DaoAuthenticationProvider nicht mehr dabei. Was genau macht dieser?
Java:
@Bean
    protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
       
        return http.csrf(customizer -> customizer.disable())
            .authorizeHttpRequests(auth->{
            auth.requestMatchers("/api/register/save").permitAll();
            auth.anyRequest().authenticated();  
        }).httpBasic(Customizer.withDefaults())
          .sessionManagement(session-> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
          .build();                                          
    }
 

Zurück
Oben