标签:spring-security spring java
我试图在Spring中实现一个非常简单的自定义身份验证过程示例,以更好地理解该概念.
我以为我现在已经准备好了一切,但是发送了一个请求以测试我实现了什么,结果导致NullPointerException可以追溯到
this.getAuthenticationManager()在我的自定义过滤器中返回null.但是我不明白为什么.不幸的是,现有的非常相似的问题并没有真正帮助我.因此,我将感谢您的帮助;这是我认为最相关的课程,请随时询问是否需要更多课程.
MyAuthenticationFilter(基于UsernamePasswordAuthenticationFilter的源代码),此行的最后一行发生错误:
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;
}
}
MyAuthenticationProvider:
@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);
}
}
解决方法:
为什么看到NullPointerException
您看到的是NullPointerException,因为您没有将AuthenticationManager连接到过滤器中.根据javadocs的AbstractAuthenticationProcessingFilter
The filter requires that you set the authenticationManager property. An AuthenticationManager is required to process the authentication request tokens created by implementing classes
在这种情况下,我确实对为什么authenticationManager没有对抽象过滤器的构造函数参数进行简化的问题scratch之以鼻.我建议在您的自定义过滤器的构造函数中强制执行此操作.
public MyAuthenticationFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login", "POST"));
this.setAuthenticationManager(authenticationManager);
}
AuthenticationManager或AuthenticationProvider
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
}
AuthenticationManagerBuilder将创建一个ProviderManager(一个AuthenticationManager).
ProviderManager是AuthenticationProvider的集合,并将尝试与它管理的每个AuthenticationProvider进行authenticate(). (这是public boolean支持(Class<?>身份验证)在AuthenticationProvider合同中非常重要的地方)
在您的配置中,您已经创建了一个ProviderManager,其中仅包含您的自定义身份验证提供程序
凉.现在我的AuthenticationManager在哪里?
可以通过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()使检查的异常冒泡
全部放在一起
...
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));
}
}
标签:spring-security,spring,java 来源: https://codeday.me/bug/20191108/2009241.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。