【问题标题】:Spring security authentication always return 401Spring 安全认证总是返回 401
【发布时间】:2020-10-03 01:47:37
【问题描述】:

我在春季遇到了身份验证问题。 我的身份验证过滤器扩展了 UsernamePasswordAuthenticationFilter。

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

private final AuthenticationManager authenticationManager;
private final RefreshTokenProvider refreshTokenProvider;
private final AccessTokenProvider accessTokenProvider = new AccessTokenProvider();

public AuthenticationFilter(AuthenticationManager authenticationManager, RefreshTokenProvider refreshTokenProvider) {
    this.authenticationManager = authenticationManager;
    this.refreshTokenProvider = refreshTokenProvider;
    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 RuntimeException(e);
    }


}

@Override
protected void successfulAuthentication(HttpServletRequest req,
                                        HttpServletResponse res,
                                        FilterChain chain,
                                        Authentication auth) throws IOException, ServletException {
    //

}

实现UserDetailsS​​ervice

@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final PasswordEncoder encoder;
    private final UserQueryRepository userQueryRepository;

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

    private UserDetails getUserDetails(UserDto user) {
        return org.springframework.security.core.userdetails.User.builder()
                .username(user.getUsername())
                .authorities(convertAuthorities(user))
                .password(encoder.encode(user.getPassword()))
                .disabled(!user.isActive())
                .build();
    }

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

还有 SecurityConfig 类

@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserQueryRepository userQueryRepository;
    private final RefreshTokenProvider refreshTokenProvider;

    @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(), refreshTokenProvider))
                .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;
    }

如果我尝试使用邮递员发送具有良好凭据的身份验证请求,在调试器模式下一切正常(AuthFilter 和 UserDetailsS​​ervice),但服务器返回 401 并且 Authfilter 中的成功身份验证方法不会调用。


收到 POST '/auth/sing-in' 的请求:

org.apache.catalina.connector.RequestFacade@27b774b2

servletPath:/auth/sing-in 路径信息:空 标题: 内容类型:应用程序/json 用户代理:PostmanRuntime/7.25.0 接受:/ 缓存控制:无缓存 邮递员令牌:c5bb3320-9c22-4d3d-93e9-628fe0e6f82a 主机:本地主机:9000 接受编码:gzip、deflate、br 连接:保活 内容长度:54

安全过滤器链:[ WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter 注销过滤器 身份验证过滤器 授权过滤器 RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter 匿名身份验证过滤器 会话管理过滤器 异常翻译过滤器 过滤器安全拦截器 ]


2020-06-13 20:52:42.048 INFO 9956 --- [nio-9000-exec-2] org.mongodb.driver.connection:打开的连接 [connectionId{localValue:2, serverValue:126}] 到127.0.0.1:27017 2020-06-13 20:52:42.258 INFO 9956 --- [nio-9000-exec-2] Spring Security 调试器:


收到 POST '/error' 的请求:

org.apache.catalina.core.ApplicationHttpRequest@fafe057

servletPath:/错误 路径信息:空 标题: 内容类型:应用程序/json 用户代理:PostmanRuntime/7.25.0 接受:/ 缓存控制:无缓存 邮递员令牌:c5bb3320-9c22-4d3d-93e9-628fe0e6f82a 主机:本地主机:9000 接受编码:gzip、deflate、br 连接:保活 内容长度:54

安全过滤器链:[ WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter 注销过滤器 身份验证过滤器 授权过滤器 RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter 匿名身份验证过滤器 会话管理过滤器 异常翻译过滤器 过滤器安全拦截器 ]


【问题讨论】:

    标签: java spring security spring-security


    【解决方案1】:

    successfulAuthentication() 方法中没有任何内容。它应该是这样的。

    @Override
    protected void successfulAuthentication(HttpServletRequest req,
                                            HttpServletResponse res,
                                            FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {
            super.successfulAuthentication(req, res, chain, auth);
            chain.doFilter(req, res);
    }
    

    抱歉,我没有注意到“successfulAuthentication 不会调用”。您能否在调试模式下共享堆栈跟踪使用

    @EnableWebSecurity(debug = true)
    

    【讨论】:

    猜你喜欢
    • 2019-02-01
    • 2021-11-18
    • 2016-10-16
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 2018-04-03
    • 2016-06-14
    相关资源
    最近更新 更多