java - 返回错误的凭据并返回 getAuthenticationManager().authenticate()

标签 java spring spring-security

我是 Spring Security 的新手,我完成了本教程:https://windoctor7.github.io/spring-jwt.html

但是我修改了一些数据库中搜索用户的代码,所以,我创建了一个@bean:

1°分开,拦截调用。

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "es.....service")
public class ServiciosConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public LoginFilter createLogin() throws Exception {
        return new LoginFilter("/login", authenticationManager());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
            .antMatchers("/login").permitAll() //permitimos el acceso a /login a cualquiera
            .anyRequest().authenticated() //cualquier otra peticion requiere autenticacion
            .and()
            // Las peticiones /login pasaran previamente por este filtro
           .addFilterBefore(createLogin(),  UsernamePasswordAuthenticationFilter.class)
            // Las demás peticiones pasarán por este filtro para validar el token
            .addFilterBefore(new JwtFilter(),
                    UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }

我拦截“登录”并在数据库中搜索用户是否存在:

public class LoginFilter extends AbstractAuthenticationProcessingFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginFilter.class);

    @Autowired
    private RolesUserRepository rolRepository;

    @Value("${ldap.base}")
    private String base;

    public LoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {

        // obtenemos el body de la peticion que asumimos viene en formato JSON
        InputStream body = req.getInputStream();

        // Realizamos un mapeo a nuestra clase User para tener ahi los datos
        User user = new ObjectMapper().readValue(body, User.class);

        // Finalmente autenticamos
        LOGGER.info("Buscando al usuario: " + user.getUsername() + " en la BD.");
        RolesUser rol = this.rolRepository.findByUser(user.getUsername());

        if (rol.getRol() != null) {
            LOGGER.info("El usuario: " + user.getUsername() + " es correcto.");

            List<GrantedAuthority> grantedAuths = AuthorityUtils.commaSeparatedStringToAuthorityList(rol.getRol());
            return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),
                    user.getPassword(), grantedAuths));
        } else {
            throw new javax.security.sasl.AuthenticationException("Credenciales inválidas.");
        }

    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
            Authentication auth) throws IOException, ServletException {
        // Si la autenticacion fue exitosa, agregamos el token a la respuesta
        JwtUtil.addAuthentication(res, auth.getName());
    }

}

用户是正确的,终于上线了:

return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),
                        user.getPassword(), grantedAuths));

我在 AbstractAuthenticationProcessingFilter.class

中遇到错误
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

if (!requiresAuthentication(request, response)) {
    chain.doFilter(request, response);

    return;
}

if (logger.isDebugEnabled()) {
    logger.debug("Request is to process authentication");
}

Authentication authResult;

try {
    authResult = attemptAuthentication(request, response);
    if (authResult == null) {
        // return immediately as subclass has indicated that it hasn't completed
        // authentication
        return;
    }
    sessionStrategy.onAuthentication(authResult, request, response);
}
catch (InternalAuthenticationServiceException failed) {
    logger.error(
            "An internal error occurred while trying to authenticate the user.",
            failed);
    unsuccessfulAuthentication(request, response, failed);

    return;
}
catch (AuthenticationException failed) {
    // Authentication failed
    unsuccessfulAuthentication(request, response, failed);

    return;
}

// Authentication success
if (continueChainBeforeSuccessfulAuthentication) {
    chain.doFilter(request, response);
}

successfulAuthentication(request, response, chain, authResult);

}

in unsuccessfulAuthentication(请求,响应,失败);

代码错误是org.springframework.security.authentication.BadCredentialsException:错误的凭据 看不懂,啥凭证???我的用户是正确的,存在于数据库中,为什么我会收到错误???我只修改 el @bean 因为我可以使用 @autowired ...谢谢...

用答案 Saad Surya 进行修改:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "es.....service")
public class ServiciosConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserServiceImpl userDetailService;

    @Bean
    public LoginFilter createLogin() throws Exception {
        return new LoginFilter("/login", authenticationManager());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().antMatchers("/login").permitAll() // permitimos el acceso a /login a
                                                                                    // cualquiera
                .anyRequest().authenticated() // cualquier otra peticion requiere autenticacion
                .and()
                // Las peticiones /login pasaran previamente por este filtro
                .addFilterBefore(createLogin(), UsernamePasswordAuthenticationFilter.class)
                // Las demás peticiones pasarán por este filtro para validar el token
                .addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }

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

因此,我删除了 LoginFilter 的逻辑:

public class LoginFilter extends AbstractAuthenticationProcessingFilter {

    public LoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {

        // obtenemos el body de la peticion que asumimos viene en formato JSON
        InputStream body = req.getInputStream();

        // Realizamos un mapeo a nuestra clase User para tener ahi los datos
        User user = new ObjectMapper().readValue(body, User.class);

        return getAuthenticationManager().authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUser(),
                            user.getPwd(),
                            Collections.emptyList()
                    )
            );

    }

现在我直接返回 getAuthenticationManager...

我使用 userDetailsS​​ervice 接口(interface)来检查凭据,并返回带有 el user 和 rol 的 obj userDetails 来创建 token jwt。

@Service
public class UserServiceImpl implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired 
    private RolesUserRepository repository;

    public void UserService(RolesUserRepository repository) {
            this.repository = repository;
        }

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        RolesUser rolUser = repository.findByUser(userName);
        if(rolUser.getRol() != null) {
          LOGGER.info("El usuario: " + userName + " es: " + rolUser.getRol());
          List<GrantedAuthority> grantedAuths = AuthorityUtils.commaSeparatedStringToAuthorityList(rolUser.getRol());
          return new MyUserPrincipal(grantedAuths,"",userName);
        }else {
            throw new AuthenticationException("Las credenciales son incorrectas.") {
            };
        }
    }

}

这里是我的类,它在存储库中检查用户并创建 MyUserPrincipal()

public class MyUserPrincipal implements UserDetails {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private List<GrantedAuthority> grantedAuths;
    private String password;
    private String userName;

    public MyUserPrincipal(List<GrantedAuthority> grantedAuths, String password, String userName) {
        this.grantedAuths = grantedAuths;
        this.password = password;
        this.userName = userName;
    }

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

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

    @Override
    public String getUsername() {
        return this.userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return true;
    }

}

带有实现 UserDetails 的类。注意,因为我修改了 isEnabled、isCredentialsNonExpired、isAccountNonLocked、isAccountNonExpired 为 true。

好吧,有了这一切,我启动了我的应用程序,但我得到了同样的错误: “身份验证失败:凭据错误”,

不同的是,现在我在类中收到错误

AbstractUserDetailsAuthenticationProvider, Line 171.
        catch (AuthenticationException exception) {
            if (cacheWasUsed) {
                // There was a problem, so try again after checking
                // we're using latest data (i.e. not from the cache)
                cacheWasUsed = false;
                user = retrieveUser(username,
                        (UsernamePasswordAuthenticationToken) authentication);
                preAuthenticationChecks.check(user);
                additionalAuthenticationChecks(user,
                        (UsernamePasswordAuthenticationToken) authentication);
            }

最佳答案

您可以实现 UserDetailsS​​ervice 并通过重写 configure(AuthenticationManagerBuilder) 方法来配置它,而不是为 LoginFilter 创建 bean WebSecurityConfigurerAdapter

public class UserService implements UserDetailsService {
    private UserRepository repository;
    public UserService(UserRepository repository) {
        this.repository = repository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        // you call to repository to get user
    }

}
<小时/>
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userDetailService;

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

关于java - 返回错误的凭据并返回 getAuthenticationManager().authenticate(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60372133/

相关文章:

spring - 如何强制 Spring Boot 重定向到 https 而不是 http?

java - 使用 Java 删除 CSS 注释

java - 如何在 Java 中比较字符串?

java - 如何在Java中将列表的列表转换为二维数组

Java + Spring + Hibernate : "order by" slow on production

java - 作为收件人列表路由器的收件人的链

spring - 如何在 spring oauth2 OAuth2AccessToken 请求或如何覆盖 OAuth2AccessTokenSupport restTemplate 变量上设置代理?

java - 如何动态限制Spring Security中的路由?

java - 将字符串解析为数组?

java - Spring Sentry 集成。事件处理器不工作(阻止健康检查)