解决:No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordA

在这里插入图片描述

博主 默语带您 Go to New World.
个人主页—— 默语 的博客👦🏻 优秀内容
《java 面试题大全》
《java 专栏》
《idea技术专区》
《spring boot 技术专区》
《MyBatis从入门到精通》
《23种设计模式》
《经典算法学习》
《spring 学习》
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨


默语是谁?

大家好,我是 默语,别名默语博主,擅长的技术领域包括Java、运维和人工智能。我的技术背景扎实,涵盖了从后端开发到前端框架的各个方面,特别是在Java 性能优化、多线程编程、算法优化等领域有深厚造诣。

目前,我活跃在CSDN、掘金、阿里云和 51CTO等平台,全网拥有超过10万的粉丝,总阅读量超过1400 万。统一 IP 名称为 默语 或者 默语博主。我是 CSDN 博客专家、阿里云专家博主和掘金博客专家,曾获博客专家、优秀社区主理人等多项荣誉,并在 2023 年度博客之星评选中名列前 50。我还是 Java 高级工程师、自媒体博主,北京城市开发者社区的主理人,拥有丰富的项目开发经验和产品设计能力。希望通过我的分享,帮助大家更好地了解和使用各类技术产品,在不断的学习过程中,可以帮助到更多的人,结交更多的朋友.


我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。


解决:No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken


摘要

在开发基于 Spring Security 的 Java 项目时,遇到 No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken 错误,是许多开发者常见的问题。本文将为你详细分析该问题的原因,并提供一个简单易懂的解决方法,附带完整代码示例和最佳实践建议,助你快速解决该问题。


引言

Spring Security 是一个功能强大的安全框架,用于处理身份验证和授权。但它的高度灵活性,也意味着配置的复杂性。
当你使用 UsernamePasswordAuthenticationToken 作为登录的认证令牌时,如果未正确配置 AuthenticationProvider,Spring Security 将无法验证用户,从而抛出 No AuthenticationProvider found 异常。

以下是问题出现的典型场景:

  1. 项目中引入了自定义的登录逻辑。
  2. 配置类未定义支持 UsernamePasswordAuthenticationToken 的认证提供器。

接下来,让我们一步步了解问题的根本原因和解决方法。


正文

1. 问题复现

当你在 Spring Security 项目中编写自定义的登录认证逻辑时,比如:

Authentication authentication = authenticationManager.authenticate(
    new UsernamePasswordAuthenticationToken(username, password)
);

运行时,抛出以下异常:

No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken

原因
Spring Security 的认证流程需要 AuthenticationProvider 对象处理特定类型的 Authentication,但项目中未正确注册支持 UsernamePasswordAuthenticationTokenAuthenticationProvider


2. 解决方法

我们可以通过以下步骤解决这个问题:

2.1 自定义 AuthenticationProvider

实现一个自定义的 AuthenticationProvider,专门处理 UsernamePasswordAuthenticationToken

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Collections;

public class CustomAuthenticationProvider implements AuthenticationProvider {

    private final PasswordEncoder passwordEncoder;

    public CustomAuthenticationProvider(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        // 模拟从数据库中查询用户
        UserDetails user = User.builder()
            .username("test_user")
            .password(passwordEncoder.encode("test_password"))
            .roles("USER")
            .build();

        if (passwordEncoder.matches(password, user.getPassword())) {
            return new UsernamePasswordAuthenticationToken(username, password, user.getAuthorities());
        } else {
            throw new RuntimeException("Authentication failed");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
2.2 配置 CustomAuthenticationProvider

将自定义的 AuthenticationProvider 注入到 Spring Security 的上下文中:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig {

    @Bean
    public AuthenticationProvider authenticationProvider(PasswordEncoder passwordEncoder) {
        return new CustomAuthenticationProvider(passwordEncoder);
    }

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

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }
}

3. 测试解决方案

创建一个简单的 REST 接口,验证登录是否正常工作:

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    private final AuthenticationManager authenticationManager;

    public AuthController(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @PostMapping("/login")
    public String login(@RequestBody LoginRequest request) {
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
        );
        return "Login successful for user: " + authentication.getName();
    }
}

class LoginRequest {
    private String username;
    private String password;

    // Getters and setters...
}

测试接口:

  • 请求示例:
POST /auth/login
Content-Type: application/json

{
  "username": "test_user",
  "password": "test_password"
}
  • 响应示例:
Login successful for user: test_user

总结

通过自定义 AuthenticationProvider 并注册到 Spring Security 上下文中,可以有效解决 No AuthenticationProvider found 问题。

核心步骤总结:

  1. 自定义 AuthenticationProvider:实现 supportsauthenticate 方法。
  2. 配置类注册 Provider:确保 Spring Security 知道如何使用该提供器。
  3. 测试与验证:确认登录流程是否正确处理了用户认证。

参考资料

  1. Spring Security 官方文档
  2. Spring Security 自定义认证机制

加个微信,一起交流吧 🚀

感谢阅读这篇文章,如果你有其他疑问,或者想与我一起探讨更多技术问题,欢迎扫码加我的微信,备注 Solitudemind 哦!

在这里插入图片描述


🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默 语

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值