Problem z uwierzytelnianiem w Spring Security

0

Cześć. Mam mały problem z spring security. Przy każdej próbie uwierzytelnienia z poziomu Postmana serwer zwraca 401. Więc tak, najpierw mam stworzony filtr który przesłania metodę attemptAuthentication z klasy UsernamePasswordAuthenticationFilter:

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    public AuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        setFilterProcessesUrl(SecurityConstants.AUTH_SIGN_IN_PATH);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        try {
            SingInRequest singInRequest = new ObjectMapper().readValue(request.getInputStream(), SingInRequest.class);

            UsernamePasswordAuthenticationToken authRequest =
                    new UsernamePasswordAuthenticationToken(singInRequest.getUsername(), singInRequest.getPassword());

            return authenticationManager.authenticate(authRequest);
        } catch (IOException e) {
            throw new SecurityException(e);
        }
    }

Dalej mam implementację UserDetailsService.

@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final PasswordEncoder encoder;
    private final UserQueryRepository userQueryRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userQueryRepository.findByUsername(username)
                .map(this::getUserDetails)
                .orElseThrow(() -> new UsernameNotFoundException("User " + username + " not found"));
    }

    private UserDetails getUserDetails(UserDto user) {
        return CustomSecurityUser.builder()
                .username(user.getUsername())
                .authorities(convertAuthorities(user))
                .password(encoder.encode(user.getPassword()))
                .active(user.isActive())
                .build();
    }

    private List<GrantedAuthority> convertAuthorities(UserDto user) {
        return user.getRoles().stream().map(role ->
                new SimpleGrantedAuthority(role.toString())
        ).collect(Collectors.toList());
    }
}

CustomSecurityUser to po prostu klasa implementująca UserDetails dodająca od siebie pole z id'kiem usera

@Builder
public class CustomSecurityUser implements UserDetails {

    @Getter
    private String id;

    private String username;

    private boolean active;

    private String password;

    private Collection<? extends GrantedAuthority> authorities;

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

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

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

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

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

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

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

Na koniec klasa konfiguracyjna

@EnableWebSecurity(debug = true)
@Configuration
@RequiredArgsConstructor
class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserQueryRepository userQueryRepository;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/auth/**").permitAll()
                .antMatchers("/book/**").authenticated()
                .and()
                .addFilter(new AuthenticationFilter(authenticationManager()))
                .addFilter(new AuthorizationFilter(authenticationManager()))
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl(passwordEncoder(), userQueryRepository);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        corsConfiguration.addAllowedOrigin("http://localhost:3000");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

}

No i problemem jest tak jak pisałem nie działające uwierzytelnianie. W trybie debugera wszystko działa dobrze, jednak mimo wszystko serwer nie uwierzytelnia i zwraca 401. Wklejam jeszcze logi z trybu debug w security.

*Request received for POST '/auth/sing-in':

org.apache.catalina.connector.RequestFacade@59c64ffb

servletPath:/auth/sing-in
pathInfo:null
headers:
content-type: application/json
user-agent: PostmanRuntime/7.25.0
accept: /
cache-control: no-cache
postman-token: fb15ec1a-6170-40a9-a1be-ec4a2dacf5fa
host: localhost:9000
accept-encoding: gzip, deflate, br
connection: keep-alive
content-length: 54

Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
AuthenticationFilter
AuthorizationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]


2020-06-17 1936.921 INFO 13916 --- [nio-9000-exec-5] Spring Security Debugger :


Request received for POST '/error':

org.apache.catalina.core.ApplicationHttpRequest@163cb088

servletPath:/error
pathInfo:null
headers:
content-type: application/json
user-agent: PostmanRuntime/7.25.0
accept: /
cache-control: no-cache
postman-token: fb15ec1a-6170-40a9-a1be-ec4a2dacf5fa
host: localhost:9000
accept-encoding: gzip, deflate, br
connection: keep-alive
content-length: 54

Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
AuthenticationFilter
AuthorizationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]


0

W sumie nie jestem w stanie odpowiedzieć od razu, ale możemy pogrzebać.
Zacznijmy od porządnego logowania - https://stackoverflow.com/a/47729991

0

Parę pomysłów:

  1. W jaki sposób w ogóle wysyłasz requesta z tego Postmana? Pokaż screena najlepiej, bo nie widzę ani cookies ani payloadu z debug logów

  2. Może gdzieś jakaś mała literówka? *Request received for POST '/auth/sing-in': (sing-in)

  3. Zaczep się debugerem w swoim filtrze i popatrz co tam się dzieje

  4. Być może kolejność filtrów trzeba zmienić? Popróbuj, popatrz tu https://stackoverflow.com/questions/25957879/filter-order-in-spring-boot#:~:text=Spring%20Security%20doesn't%20set,default%20order%20which%20is%20LOWEST_PRECEDENCE.

1 użytkowników online, w tym zalogowanych: 0, gości: 1