spring-security Spring Security getAuthenticationManager()在自定义过滤器中返回空值

cxfofazt  于 2022-11-11  发布在  Spring
关注(0)|答案(3)|浏览(308)

我试图在Spring中实现一个非常简单的自定义身份验证过程的示例,以便更好地理解这个概念。
我以为我现在已经准备好了一切,但是发送一个请求来测试我实现的东西,结果导致了一个NullPointerException,可以追溯到 this.getAuthenticationManager() 在我的自定义过滤器中返回null。但是我不明白为什么。很不幸,这个非常相似的现有问题并没有真正帮助我。所以我会感谢帮助;这里是我认为最相关的课程,如果还需要的话,请随时询问。

  • MyAuthenticationFilter*(基于用户名密码AuthenticationFilter的源代码),错误发生在以下代码的最后一行:
public class MyAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public MyAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            if (!request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException(
                        "Authentication method not supported: " + request.getMethod());
            }

            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String secondSecret = request.getParameter("secondSecret");

            if (username == null) {
                username = "";
            }

            if (password == null) {
                password = "";
            }

            username = username.trim();

            MyAuthenticationToken authRequest = new MyAuthenticationToken(username, new MyCredentials(password, secondSecret));

            return this.getAuthenticationManager().authenticate(authRequest);
    }
}

我的配置类:

@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan
public class AppConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyAuthenticationProvider myAuthenticationProvider;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new MyAuthenticationFilter(), BasicAuthenticationFilter.class)
                .authorizeRequests().antMatchers("/**")
                    .hasAnyRole()
                    .anyRequest()
                    .authenticated()
                    .and()
                .csrf().disable();
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
  • 我的验证提供者 *:
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        MyAuthenticationToken myAuthenticationToken = (MyAuthenticationToken) authentication;
        MyCredentials credentials = (MyCredentials) myAuthenticationToken.getCredentials();
        if (credentials.getPassword().equals("sesamOeffneDich") && credentials.getSecondSecret().equals(MyAuthenticationToken.SECOND_SECRET)) {
            myAuthenticationToken.setAuthenticated(true);
            return myAuthenticationToken;
        } else {
            throw new BadCredentialsException("Bad credentials supplied!");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MyAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
nfs0ujit

nfs0ujit1#

为什么会出现NullPointerException

您看到的是NullPointerException,因为您的过滤器中没有连接AuthenticationManager
筛选器要求您设置authenticationManager属性。需要AuthenticationManager来处理通过实现类创建的身份验证请求令牌
在这种情况下,我确实想不通为什么authenticationManager没有为这个抽象过滤器的构造函数参数进行剪切。我建议在自定义过滤器的构造函数中强制执行这一点。

public MyAuthenticationFilter(AuthenticationManager authenticationManager) {
    super(new AntPathRequestMatcher("/login", "POST"));
    this.setAuthenticationManager(authenticationManager);
}

验证管理器或验证提供程序

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

AuthenticationManagerBuilder将创建一个ProviderManager (an AuthenticationManager)
ProviderManagerAuthenticationProvider的集合,它将尝试对它管理的每个AuthenticationProvider执行authenticate()。(这是public boolean supports(Class<?> authentication)AuthenticationProvider协定中极其重要的地方)
在您的配置中,您已经创建了一个仅包含自定义Authentication ProviderProviderManager

太棒了。现在我的验证管理器在哪里?

WebSecurityConfigurerAdapter中,可以通过this.authenticationManager()获取由configure()方法生成的AuthenticationManager

@Bean
public AuthenticationManager authenticationManager throws Exception() {
    this.authenticationManager();
}

建议事项

创建您自己的ProviderManager确实有它的好处,因为它将是明确的,并在您的控制范围内。

@Bean
public AuthenticationManager authenticationManager() {
    return new ProviderManager(Arrays.asList(myAuthenticationProvider));
}

这将使您可以灵活地放置AuthenticationManager Bean,并避免:

  • Bean配置中潜在的循环依赖关系问题
  • 由于调用this.authenticationManager()而使选中的Exception冒泡
    将一切整合
...
public class AppConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyAuthenticationProvider myAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
        ...
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Arrays.asList(myAuthenticationProvider));
    }
}
ffx8fchx

ffx8fchx2#

您应该为过滤器设置身份验证管理器。

@Bean 
    public MyAuthenticationFilter myAuthenticationFilter() {
        MyAuthenticationFilter res = new MyAuthenticationFilter();
        try {
            res.setAuthenticationManager(authenticationManagerBean());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return res;
    }

并使用修改configure方法
一个月一个月...

u3r8eeie

u3r8eeie3#

在我的情况下没有帮助除了这:

public AuthenticationManager authenticationManager() {
    return new ProviderManager(Arrays.asList(tokenAuthenticationProvider, 
                                             apiKeyAuthenticationProvider));
}

相关问题