需要找不到类型为“ org.springframework.security.authentication.AuthenticationManager”的bean。春季安全信息

时间:2019-11-02 12:21:59

标签: spring spring-boot spring-mvc spring-security

我正在尝试使用spring boot实施一个用于弹簧安全性的示例演示,以检查身份验证。我正在尝试实施一项针对弹簧安全性的基本锻炼,并获得以下消息,

Description:

Parameter 0 of constructor in com.spacestudy.service.CustomAuthenticationProvider required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.

Action:

Consider defining a bean of type 'org.springframework.security.web.AuthenticationEntryPoint' in your configuration.

我的安全配置类SecurityConfig.java,

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private AuthenticationEntryPoint authEntryPoint;

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .addFilter(new ApplicationContextHeaderFilter((ApplicationContext) authenticationManager()));
    }
}

我的BasicAuthenticationFilter实现如下所示,

@Component
public class  CustomAuthenticationProvider  extends  BasicAuthenticationFilter    { 

public CustomAuthenticationProvider(AuthenticationManager authenticationManager) {
    super(authenticationManager);
    // TODO Auto-generated constructor stub
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    filterChain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
   String bearerToken = request.getHeader("accessToken");
String username = "test";
String password = "test";
    if (username != null && !username.isEmpty()) {
        return new UsernamePasswordAuthenticationToken(username, null, null);
      }
    return null;
    }
 }

如果我在此方向错误,有人可以指导我解决此问题吗?

3 个答案:

答案 0 :(得分:1)

您的代码中有很多问题。

  1. (ApplicationContext) authenticationManager()
    您不能将AuthenticationManager投射到ApplicationContext

  2. .addFilter(new ApplicationContextHeaderFilter(...))
    我不知道您为什么将ApplicationContextHeaderFilter用于简单的演示应用程序。

    • 您应该首选BasicAuthenticationFilter或什至为HttpSecurity.httpBasic()提供的简单默认配置

    • 您应该首选UsernamePasswordAuthenticationFilter甚至是HttpSecurity中带有.formLogin()的简单默认配置

  3. CustomAuthenticationProvider extends BasicAuthenticationFilter
    身份验证提供程序是实现AuthenticationProvider接口的提供程序。在您的情况下,命名应为xxxAuthFilter

  4. 您在下面的代码中没有执行任何操作。(丢失了现有的身份验证对象,并在不创建有效身份验证对象的情况下将其重新设置。)

UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);

从AuthenticationManager和AuthFilters实现的角度来看,
对于添加过滤器,您可以添加Spring Security提供的过滤器的任何实现,如下所示
.addFilter(AnyFilterImplementationFromThisLink) (但并非所有过滤器都是身份验证过滤器。其中,身份验证过滤器将尝试使用配置的authenticationManager进行身份验证) 例如,如果您考虑UsernamePasswordAuthenticationFilterBasicAuthenticationFilter

  

您应注意设置AuthenticationManager,其中您的身份验证管理器应覆盖authenticate()方法,并应返回Authentication对象(其中Authentication对象将具有身份验证主体,凭据并授予权限列表)

如果您不想实现身份验证管理器...
以简单的方式在您的过滤器(OncePerRequestFilter的实现)中,doFilterInternal()方法在SecurityContext中设置Authentication对象。
List<GrantedAuthority> authorityList = new ArrayList<>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
authorityList.add(authority);
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password, authorityList);
//Note UsernamePasswordAuthenticationToken implements Authentication
SecurityContextHolder.getContext().setAuthentication(authToken);

任何身份验证过滤器的工作方式是:如果存在有效的Authentication对象,则过滤器链将继续进行而不会尝试进行身份验证,否则它将通过被覆盖的attemptAuthentication方法attemptAuthentication()进行过滤。
但是您的ApplicationContextHeaderFilterOncePerRequestFilter的实现,其中没有attemptAuthentication(),并且我不知道ApplicationContextHeaderFilter的顺序,如果顺序是在创建安全上下文之后,那么您可以将身份验证对象设置为安全上下文。

答案 1 :(得分:0)

我不确定,但CustomAuthenticationProvider implement AuthenticationProviderAuthenticationManager不应仅仅是身份验证提供程序的容器,而且似乎还没有。

查看此网站以获取更多信息 https://www.baeldung.com/spring-security-authentication-provider

答案 2 :(得分:-1)

您的错误似乎是AuthenticationManager不作为Spring Bean出现。

选项1

在Spring Bean中注册AuthenticationManager。 Spring提供的所有功能都可以直接在您的SecurityConfig类中通过覆盖WebSecurityConfigurerAdapter#authenticationManagerBean方法(例如在其documentation中进行解释)来做到这一点

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

选项2

避免在Spring中注册AuthenticationManager,而直接注册CustomAuthenticationProvider类。

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public CustomAuthenticationProvider authenticationProvider() throws Exception {
        return new CustomAuthenticationProvider(authenticationManager());
    }
}

请不要忘记使用此方法删除@Component类上的CustomAuthenticationProvider注释。