自定义 AuthenticationProvider ,UserDetailsService的实现类@Autowired 为null


项目场景:

整合spring security OAuth2自定义AuthenticationProvider 登录认证 签发token

问题描述:

在自定义 AuthenticationProvider 时 发现UserDetailsService 的实现类 UserService 一直注入不进去,为null

自定义 AuthenticationProvider 通过 username直接登录

package com.example.sso.provider;

import com.example.sso.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.UserDetails;

@Slf4j
public class UsernameAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    UserService userService;

    public UsernameAuthenticationProvider() {
        log.info("UsernameAuthenticationProvider  loading......");
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        String username = (String) authentication.getPrincipal();
        UserDetails user = userService.loadUserByUsername(username);
        if (null != user) {
            return new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(), user.getAuthorities());
        }
        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
         return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

解决办法,看最后三组代码
重写

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

在该配置类,注入UserDetailsService的实现类UserService,并将其设置到AuthenticationManagerBuilder 中。

然后将自定义的 UsernameAuthenticationProvider 在此实例化。然后将其注入到 AuthenticationManagerBuilder 中,他是用来管理所有的provider的

package com.example.sso.config;

import com.example.sso.provider.UsernameAuthenticationProvider;
import com.example.sso.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {

    //对外放开某些接口
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/login/getUser");
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/**").authenticated().anyRequest().authenticated();//所有请求都需要验证

               // .anyRequest().permitAll(); //其他所有请求都不需要验证
    }

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

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Autowired
    UserService userService;

    @Bean
    public UsernameAuthenticationProvider usernameAuthenticationProvider() {
        return new UsernameAuthenticationProvider();
    }

    //添加自定义的provider
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(usernameAuthenticationProvider());
        auth.userDetailsService(userService);
    }

}

相关