Spring Security教程(7)---- 解决UsernameNotFoundException无法被捕获的问题
2014-01-16 16:26
746 查看
这个教程是我在往项目中一点一点添加 Spring Security的过程的一个笔记,也是我学习 Spring Security的一个过程。
在解决这个问题之前要先说一点authentication-provider默认加载的是DaoAuthenticationProvider类。
完成了上一章的内容后在测试的时候发现在UserDetailsService中抛出的UsernameNotFoundException无法被捕获。于是找到DaoAuthenticationProvider,源码看了好几遍没有看出端倪。然后直接查看最顶级的接口AuthenticationProvider。发现它只有一个方法如下
然后找到DaoAuthenticationProvider的父类AbstractUserDetailsAuthenticationProvider的authenticate方法,发现了这段代码。
注意:如果在authentication-provider配置中用ref指定AuthenticationProvider则authentication-provider的子元素将都不可以用。
即下面的这种配置是错误的
SaltSource是一个接口有两个实现类SystemWideSaltSource和ReflectionSaltSource。
SystemWideSaltSource :只能指定固定值
ReflectionSaltSource:可以指定UserDetails的属性,这里我们用的就是它
这样的话就可以保证在抛出UsernameNotFoundException时,前台能显示出来错误信息,如下所示。
在上一章中忘了介绍如何在前台显示登录是的异常信息,在这里补上。
UsernamePasswordAuthenticationFilter认证失败后,异常信息会写到Session中,key为SPRING_SECURITY_LAST_EXCEPTION
可以通过El表达式来获取到异常的信息。
在解决这个问题之前要先说一点authentication-provider默认加载的是DaoAuthenticationProvider类。
完成了上一章的内容后在测试的时候发现在UserDetailsService中抛出的UsernameNotFoundException无法被捕获。于是找到DaoAuthenticationProvider,源码看了好几遍没有看出端倪。然后直接查看最顶级的接口AuthenticationProvider。发现它只有一个方法如下
Authentication authenticate(Authentication authentication) throws AuthenticationException;抛出AuthenticationException异常,而UsernameNotFoundException是AuthenticationException的子类,那问题应该就出在authenticate这个方法上了。
然后找到DaoAuthenticationProvider的父类AbstractUserDetailsAuthenticationProvider的authenticate方法,发现了这段代码。
try { user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { logger.debug("User '" + username + "' not found"); if (hideUserNotFoundExceptions) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } }它这里有个hideUserNotFoundExceptions属性,默认是true。这样的话即便我们抛出了UsernameNotFoundException它也会转为BadCredentialsException,所以我们需要将hideUserNotFoundExceptions属性的值设为false,而在上一章中的那种配置方法是没有办法为其属性赋值的所以我们要手动注入.authentication-provider,所以配置就变成了下面的内容
<sec:authentication-manager> <sec:authentication-provider ref="authenticationProvider" /> </sec:authentication-manager> <bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <property name="hideUserNotFoundExceptions" value="false" /> <property name="userDetailsService" ref="userDetailService" /> <property name="userCache" ref="userCache" /> <property name="messageSource" ref="messageSource" /> <property name="passwordEncoder" ref="passwordEncode" /> <property name="saltSource" ref="saltSource" /> </bean> <!-- 配置密码加密类 --> <bean id="passwordEncode" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" /> <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource"> <property name="userPropertyToUse" value="username"/> </bean>
注意:如果在authentication-provider配置中用ref指定AuthenticationProvider则authentication-provider的子元素将都不可以用。
即下面的这种配置是错误的
<sec:authentication-manager> <sec:authentication-provider ref="authenticationProvider" > <sec:password-encoder ref="passwordEncode"> <sec:salt-source user-property="username"/> </sec:password-encoder> </sec:authentication-provider> </sec:authentication-manager>所以我们的盐值加密就需要注入到AuthenticationProvider中了。
SaltSource是一个接口有两个实现类SystemWideSaltSource和ReflectionSaltSource。
SystemWideSaltSource :只能指定固定值
ReflectionSaltSource:可以指定UserDetails的属性,这里我们用的就是它
这样的话就可以保证在抛出UsernameNotFoundException时,前台能显示出来错误信息,如下所示。
在上一章中忘了介绍如何在前台显示登录是的异常信息,在这里补上。
UsernamePasswordAuthenticationFilter认证失败后,异常信息会写到Session中,key为SPRING_SECURITY_LAST_EXCEPTION
可以通过El表达式来获取到异常的信息。
${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
相关文章推荐
- Spring Security教程(7)---- 解决UsernameNotFoundException无法被捕获的问题
- Spring Security教程(7)---- 解决UsernameNotFoundException无法被捕获的问题
- Spring Security教程(7)---- 解决UsernameNotFoundException无法被捕获的问题
- hbase无法启动Regionserver:ClassNotFoundException: org.apache.hadoop.util.PlatformName问题解决
- 解决文件无法上传的问题,错误信息:System.IO.DirectoryNotFoundException: Could not find a part of the path.
- ELK菜鸟手记 (三) - X-Pack权限控制之给Kibana加上登录控制以及index_not_found_exception问题解决
- 解决问题 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
- java.lang.ClassNotFoundException: com.google.gson.Gson 问题解决
- 关于Android中android.content.res.Resources$NotFoundException: String resource ID #0x9这类问题的解决
- 异常详细信息: System.DllNotFoundException: 无法加载 DLL (oci.dll)的解决办法
- java.lang.ClassNotFoundException: org.hibernate.Session问题解决
- FileNotFoundException问题的解决
- 【解决】SSH问题(四)Java.Lang.ClassNotFoundException: Org.Springframework.Transaction.TransactionException
- java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决
- java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener问题解决
- 解决 Hadoop 集群执行包含 third-part lib 的 jar包的 ClassNotFoundException 问题
- Web项目中诡异的java.lang.ClassNotFoundException: ch.qos.lorgback.classic.PatternLayout问题解决
- ClassNotFoundException: org.apache.axis2.transport.http.AxisAdminServlet(亲测,管用!已经在这个网站解决好多问题了)
- 【已解决】Windows Service 问题System.IO.FileNotFoundException: 未能加载文件或程序集“file:///”或它 的某一个依赖项。系统找不到指定的文件。。
- spark-submit ClassNotFoundException的问题解决