spring security authenticationProvider用法及关闭不隐藏UserNotFoundException的解决
2017-04-21 13:57
357 查看
这两天采用了spring security做登录验证,上一篇说到了增加图形验证码的解决办法,我们在config中增加了一个authenticationProvider的实现类。接下来我遇到的问题是用户登录失败(用户不存在或密码错误)之后,security框架直接返回的是验证失败。而我的需求是将用户不存在和密码错误区分开来,然后做不同的后续工作。
出现这个问题的配置是:
因发现UserNotFoundException异常是在DaoAuthenticationProvider中被屏蔽掉的,而DaoAuthenticationProvider中有个属性hideUserNotFoundExceptions,默认是ture,也就是说要想抛出UserNotFoundException,需要把hideUserNotFoundExceptions设为false。
于是增加了一个DaoAuthenticationProvider的配置
出现的结果是调用了两次userDetailsService中的验证,UserNotFoundException还是被屏蔽掉了。
经过源码跟踪,发现了ProviderManager这个类,这个类中有这么一段代码:
从上边的代码可以看出,对于AuthenticationProvider,只要配置几个provider,就会执行几个,但我在config中只配了两个,为什么会执行三个呢?
最后发现原因在于
这两个会默认在providerlist中增加一个DaoAuthenticationProvider,看到这里果断将这两行注释掉。再次测试,完美通过。UserNotFoundException也抛出来了
下面总结下authenticationProvider:
1、验证过程中,可以增加多个authenticationProvider,来完成不同的验证工作
2、根据验证的先后顺序,需要注意authenticationProvider设置的先后顺序。
3、如果抛出异常,即可停止的话,不能抛出AuthenticationException
4、每个authenticationProvider都要配置一个UserDetailsService的实现类
5、如果不使用DaoAuthenticationProvider或要重新配置,就直接使用auth.authenticationProvider()方法,不要使用auth .userDetailsService()
出现这个问题的配置是:
…… @Inject public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthenticationProvider) .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } ……
因发现UserNotFoundException异常是在DaoAuthenticationProvider中被屏蔽掉的,而DaoAuthenticationProvider中有个属性hideUserNotFoundExceptions,默认是ture,也就是说要想抛出UserNotFoundException,需要把hideUserNotFoundExceptions设为false。
于是增加了一个DaoAuthenticationProvider的配置
@Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(passwordEncoder()); return provider; } @Inject public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthenticationProvider) .authenticationProvider(authenticationProvider()) //增加 .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); }
出现的结果是调用了两次userDetailsService中的验证,UserNotFoundException还是被屏蔽掉了。
经过源码跟踪,发现了ProviderManager这个类,这个类中有这么一段代码:
…… for (AuthenticationProvider provider : getProviders()) { if (!provider.supports(toTest)) { continue; } if (debug) { logger.debug("Authentication attempt using " + provider.getClass().getName()); } try { result = provider.authenticate(authentication); if (result != null) { copyDetails(authentication, result); break; } } catch (AccountStatusException e) { prepareException(e, authentication); throw e; } catch (InternalAuthenticationServiceException e) { prepareException(e, authentication); throw e; } catch (AuthenticationException e) { lastException = e; } } ……
从上边的代码可以看出,对于AuthenticationProvider,只要配置几个provider,就会执行几个,但我在config中只配了两个,为什么会执行三个呢?
最后发现原因在于
auth .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder());
这两个会默认在providerlist中增加一个DaoAuthenticationProvider,看到这里果断将这两行注释掉。再次测试,完美通过。UserNotFoundException也抛出来了
下面总结下authenticationProvider:
1、验证过程中,可以增加多个authenticationProvider,来完成不同的验证工作
2、根据验证的先后顺序,需要注意authenticationProvider设置的先后顺序。
3、如果抛出异常,即可停止的话,不能抛出AuthenticationException
4、每个authenticationProvider都要配置一个UserDetailsService的实现类
5、如果不使用DaoAuthenticationProvider或要重新配置,就直接使用auth.authenticationProvider()方法,不要使用auth .userDetailsService()
相关文章推荐
- org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityC
- 【Bug解决】Spring配置错误:java.io.FileNotFoundException: class path resource [cxd/entity/User.hbm.xml] canno
- 真正解决问题:maven eclipse tomcat java.lang.ClassNotFoundException: org.springframework.web.context.Contex
- 解决问题 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
- GWT + Spring : javax.naming.NameNotFoundException: Name userDao is not bound in this Context
- 解决ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
- spring集成quartz中java.lang.ClassNotFoundException: org.quartz.impl.JobDetailImpl异常解决方法
- java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决
- java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener的解决办法
- 深度解决 SecurityException: User has not given permission to device UsbDevice
- 解决在tomecat启动时报 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListen
- 解决在tomecat启动时报 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListen
- 【解决】spring中集成hessian报异常,ClassNotFoundException:com.caucho.hessian.io.HessianDebugOutputStream
- java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决
- 真正解决问题:maven eclipse tomcat java.lang.ClassNotFoundException: org.springframework.web.context.Contex
- Java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListenerj解决方法
- 搭建项目Maven+springMVC+hibernate时,JUnit测试出现报ClassNotFoundException错误的解决
- 【spring-security】nested exception is java.lang.ClassNotFoundException: org.springframework.security.
- 【解决】SSH问题(四)Java.Lang.ClassNotFoundException: Org.Springframework.Transaction.TransactionException
- java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决