SpringSecurity自定义AuthenticationProvider无法@Autowire的解决

如果在使用Spring Security时,遇到需要自定义 AuthenticationProvider 的情况,同时自定义的 AuthenticationProvider 中需要使用 @Autowired注入其他的bean,却发现无法注入的情况,此时可以按照以下步骤进行解决。

问题背景

在使用Spring Security时,如果需要自定义 AuthenticationProvider,可能需要注入一些其他的bean,例如 UserDetailsService 等。在自定义的 AuthenticationProvider 中使用 @Autowired 或者 @Resource 进行注入时,可能会失败,导致注入的bean为 null

解决步骤

1.自定义 AuthenticationProvider

首先,我们需要自定义一个 AuthenticationProvider 类,例如下面的代码:

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

在这个类中,我们希望通过 @Autowired 注入 UserDetailsService

2.创建一个配置类

接下来,我们需要创建一个配置类,将 MyAuthenticationProvider 添加到 Spring Security 配置中,并将 UserDetailsService 注册到 Spring 容器中。例如下面的代码:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationProvider myAuthenticationProvider;

    @Bean
    public UserDetailsService userDetailsService() {
        // create user details service
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(myAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // configure http security
    }
}

在这个配置类中,我们通过 @Autowired 注入了 MyAuthenticationProvider。同时,我们创建了一个 UserDetailsService bean,并将其注册到 Spring 容器中。在 configure 方法中,我们将 MyAuthenticationProvider 添加到 AuthenticationManagerBuilder 中。

3.使用 @DependsOn 注解

为了避免 Spring 容器在初始化 MyAuthenticationProvider 时,还未初始化 UserDetailsService bean,我们可以在 MyAuthenticationProvider 中使用 @DependsOn 注解来保证 bean 初始化的顺序。例如:

@Component
@DependsOn("userDetailsService")
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

在这个例子中,我们使用 @DependsOn 注解来告诉 Spring 容器,MyAuthenticationProvider 依赖于名为 userDetailsService 的bean。这样确保了在初始化 MyAuthenticationProvider 之前,UserDetailsService bean已经被初始化。

4.使用 BeanPostProcessor

除了使用 @DependsOn 注解,还可以使用 BeanPostProcessor 来解决这个问题。首先,我们需要创建一个 BeanPostProcessor 类,例如下面的代码:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyAuthenticationProvider) {
            ((MyAuthenticationProvider) bean).setUserDetailsService(userDetailsService);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

在这个 BeanPostProcessor 类中,我们通过 @Autowired 注入了 UserDetailsService。然后,在 postProcessBeforeInitialization 方法中,我们对 MyAuthenticationProvider 进行判断并进行设置。

接下来,在我们的 MyAuthenticationProvider 类中,我们要添加 setter 方法来设置 UserDetailsService

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

在这个 MyAuthenticationProvider 类中,我们添加了一个 setUserDetailsService 方法,用于设置 UserDetailsService

示例演示

以下为两个示例代码:

示例一

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationProvider myAuthenticationProvider;

    @Bean
    public UserDetailsService userDetailsService() {
        // create user details service
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(myAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // configure http security
    }
}

@Component
@DependsOn("userDetailsService")
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

示例二

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationProvider myAuthenticationProvider;

    @Bean
    public UserDetailsService userDetailsService() {
        // create user details service
    }

    @Autowired
    public void setUserDetailsService(UserDetailsService userDetailsService) {
        myAuthenticationProvider.setUserDetailsService(userDetailsService);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(myAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // configure http security
    }
}

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyAuthenticationProvider) {
            ((MyAuthenticationProvider) bean).setUserDetailsService(userDetailsService);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // do authentication
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity自定义AuthenticationProvider无法@Autowire的解决 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Springboot使用influxDB时序数据库的实现

    接下来我将详细讲解“Springboot使用influxDB时序数据库的实现”的完整攻略。首先需要明确的是,influxDB是一个高性能的时序数据库,专门用于处理时间序列数据。而Springboot是一个基于Spring框架的应用程序快速开发框架。 引入influxDB依赖 在Springboot项目的pom.xml文件中,添加以下依赖: <depen…

    Java 2023年5月20日
    00
  • Java简单计算两个日期月数差的方法

    Java计算两个日期月数差的方法可以分为以下几个步骤: 将两个日期按照年、月、日拆分成年、月、日分别存储; 计算两个日期之间相差的总月数以及剩余天数; 根据剩余天数是否大于零进行判断,如果是则月数加一。 代码实现如下: import java.time.LocalDate; import java.time.Period; public class Date…

    Java 2023年5月20日
    00
  • 在Eclipse中在线安装Emmet和图文使用教程

    下面是在Eclipse中在线安装Emmet和图文使用教程的完整攻略: 在Eclipse中在线安装Emmet 打开Eclipse,点击菜单栏的“Help” -> “Eclipse Marketplace”; 在弹出的窗口搜索框中,输入“Emmet”,然后点击搜索按钮; 在搜索结果中,找到“Emmet – The Essential Toolkit for…

    Java 2023年6月15日
    00
  • 基于SpringMVC入门案例及讲解

    以下是关于“基于SpringMVC入门案例及讲解”的完整攻略,其中包含两个示例。 1. 前言 SpringMVC是一种常用的Java Web开发框架,其核心思想是基于MVC模式来实现Web应用程序开发。本攻略将详细讲解基于SpringMVC入门案例及讲解,包括SpringMVC的基本概念、配置方法以及一个示例。 2. SpringMVC的基本概念 以下是Sp…

    Java 2023年5月16日
    00
  • 超详细介绍idea中java程序打jar包的两种方式

    下面为您详细介绍IDEA中Java程序打jar包的两种方式。 一、通过Maven插件打jar包 1. 配置Maven 首先需要保证您的项目已经配置好了Maven,可以在IDEA的Settings中查看。 2. POM文件配置 然后,在Maven所管理的工程项目的pom.xml文件中加入以下代码: <build> <plugins> &…

    Java 2023年5月26日
    00
  • Java 如何使用JDBC连接数据库

    下面是Java如何使用JDBC连接数据库的完整攻略: 1. 下载需要的jar包 连接数据库需要使用JDBC驱动。不同的数据库需要使用不同版本的JDBC驱动,因此需要根据所使用的数据库下载相应的JDBC驱动。一般情况下,可以在数据库官方网站下载。 2. 加载JDBC驱动 在使用JDBC之前,需要先加载JDBC驱动。可以使用Class.forName()方法来加…

    Java 2023年5月19日
    00
  • Java数组实现动态初始化的实例详解

    Java数组实现动态初始化的实例详解 在Java中,我们可以通过数组来存储具有相同类型的多个变量。通过动态初始化,我们可以在声明数组时直接为数组元素分配空间并进行初始化。 数组动态初始化的语法 Java中动态初始化数组可以按如下的方式进行: DataType[] arrayName = new DataType[arrayLength]; 其中,DataTy…

    Java 2023年5月26日
    00
  • Java的MyBatis框架中关键的XML字段映射的配置参数详解

    关于“Java的MyBatis框架中关键的XML字段映射的配置参数详解”,下面是完整的攻略: 什么是MyBatis框架 MyBatis 框架,是一款支持普通SQL查询和存储过程的优秀持久层框架。MyBatis 可以使用简单的 XML或注解 ,将接口和 Java的pojo(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部