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

yizhihongxing

如果在使用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日

相关文章

  • Hibernate框架数据分页技术实例分析

    Hibernate框架数据分页技术实例分析 简介 Hibernate框架是一个开源的Java持久层框架,具有高级对象/关系映射(ORM)功能,可实现Java类与数据库表的映射。在实际开发中,为了提高系统的性能和用户体验,常需要使用分页技术来处理大量数据的展示。本文将介绍如何使用Hibernate框架实现数据分页功能。 实现分页的步骤 步骤一:配置Hibern…

    Java 2023年5月19日
    00
  • 详解Quartz 与 Spring框架集成的三种方式

    详解Quartz 与 Spring框架集成的三种方式如下: 一、通过Spring的配置方式 1. 引入Quartz依赖 在pom.xml文件中引入Quartz的依赖,示例代码如下: <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>…

    Java 2023年5月19日
    00
  • SpringBoot后端进行数据校验JSR303的使用详解

    下面是关于“SpringBoot后端进行数据校验JSR303的使用详解”的完整攻略。 一、什么是JSR303校验 JSR303是Java Bean Validation规范的一部分,用于数据验证,可以用于校验数据的正确性,比如校验输入的参数是否符合要求等。在SpringBoot应用中,可以方便地使用JSR303进行数据校验。 二、如何在SpringBoot中…

    Java 2023年5月20日
    00
  • Spring Boot教程之必须了解的核心概念

    下面我将为你讲解Spring Boot教程之必须了解的核心概念的完整攻略。 Spring Boot教程之必须了解的核心概念 Spring Boot是一个基于Spring Framework的快速开发框架,它可以大大简化Spring应用的初始配置。在学习Spring Boot之前,我们需要了解一些核心概念以便更好地理解和应用。 1. Spring Boot的自…

    Java 2023年5月15日
    00
  • spring boot与spring mvc的区别及功能介绍

    区别: Spring Boot和Spring MVC都是Spring框架的一部分。Spring MVC是一种基于MVC(Model-View-Controller)的Web框架,用于构建Web应用程序,而Spring Boot则是一个用于简化Spring应用程序开发的框架,它可以在开发过程中自动配置和管理一些常见的Spring功能,而无需进行手动配置。因此,…

    Java 2023年5月15日
    00
  • 微信小程序微信登录的实现方法详解(JAVA后台)

    下面是详细的攻略: 背景介绍 微信小程序微信登录是指用户可以通过微信账号快速登录小程序,无需再次注册账号。实现微信登录的关键在于后台服务器实现微信的登录认证功能。本文将详细讲解如何在Java后台实现微信登录的功能。 实现方法 实现微信登录功能的具体步骤如下: 1.前端页面添加微信登录按钮 <button type="primary"…

    Java 2023年5月23日
    00
  • Java8 Instant时间戳使用小记

    Java8 Instant时间戳使用小记 1. Instant是什么? Instant是Java8中新引入的一个时间类,它用于代表时间轴上的一个时间点。Instant以Unix时间戳的格式存储时间,精确到纳秒。 2. Instant的创建 创建Instant对象有多种方法,例如: 2.1. 通过ofEpochSecond方法创建 使用Unix时间戳(秒数)创…

    Java 2023年5月20日
    00
  • Java 中的 BufferedWriter 介绍_动力节点Java学院整理

    Java 中的 BufferedWriter 介绍 什么是 BufferedWriter BufferedWriter 是 Java.io 包中提供的一个字符缓冲输出流,它内部封装了一个字符缓冲区(Buffer),可以提高字符输出效率。 BufferedWriter 的构造方法 BufferedWriter 提供了两个构造方法: public Buffere…

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