使用SpringSecurity3用户验证(异常信息,验证码)
1. 自定义user-service后,封装自定义异常信息返回
通常情况下,抛UsernameNotFoundException异常信息是捕捉不了,跟踪源码后发现
- 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,但前台还是只能捕获Bad credentials的问题。
解决办法我们可以直接覆盖 org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider 的类,然后修改hideUserNotFoundExceptions为false。
当然,这样的解决办法并不好。所以,我们还是走正规的途径,自定义 org.springframework.security.authentication.dao.DaoAuthenticationProvider 来替换默认的即可,即修改配置文件并定义provider,这就是IoC的伟大之处。
原来authentication-manager中简单的定义user-service-ref
- <authentication-manager alias="authenticationManager">
- <authentication-provider user-service-ref="myUserDetailsService">
- <!-- 密码加密方式 -->
- <password-encoder hash="md5" />
- </authentication-provider>
- </authentication-manager>
现在修改如下:
- <authentication-manager alias="authenticationManager">
- <authentication-provider ref="authenticationProvider" />
- </authentication-manager>
- <b:bean id="authenticationProvider"
- class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
- <b:property name="userDetailsService" ref="myUserDetailsService" />
- <b:property name="hideUserNotFoundExceptions" value="false" />
- <b:property name="passwordEncoder" ref="passwordEncoder"></b:property>
- </b:bean>
- <b:bean
- class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"
- id="passwordEncoder"></b:bean>
这样修改后,在登录页面获取的异常已经是自己抛出去的UsernameNotFoundException了。
(注:这里保留了md5加密方式,但是原始的加密,没加salt,之后会继续修改为安全性高一些的md5+salt加密。现在这世道普通的md5加密和明文没多大区别。)
2. 国际化资源i18n信息
若想封装国际化资源信息到页面(不想打硬编码信息到代码内),又不想自己构造Properties对象的话,可以参考SpringSecurity3中的获取资源文件方法。(也是看源码的时候学习到的)
在SpringSecurity3中的message都是通过这样的方式得到的:
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- public SpringSecurityMessageSource() {
- setBasename("org.springframework.security.messages");
- }
- public class SpringMessageSource extends ResourceBundleMessageSource {
- // ~ Constructors
- // ===================================================================================================
- public SpringMessageSource() {
- setBasename("com.foo.resources.messages_zh_CN");
- }
- // ~ Methods
- // ========================================================================================================
- public static MessageSourceAccessor getAccessor() {
- return new MessageSourceAccessor(new SpringMessageSource());
- }
- }
- private MessageSourceAccessor messages = SpringMessageSource.getAccessor();
- ....
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException, DataAccessException {
- if (StringUtils.isBlank(username)) {
- throw new UsernameNotFoundException(
- messages.getMessage("PasswordComparisonAuthenticator.badCredentials"),
- username);
- }
- ...
- }
- <custom-filter before="FORM_LOGIN_FILTER" ref="validateCodeAuthenticationFilter" />
- <b:bean id="validateCodeAuthenticationFilter"
- class="com.foo.security.ValidateCodeAuthenticationFilter">
- <b:property name="postOnly" value="false"></b:property>
- <b:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></b:property>
- <b:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></b:property>
- <b:property name="authenticationManager" ref="authenticationManager"></b:property>
- </b:bean>
- <b:bean id="loginLogAuthenticationSuccessHandler"
- class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
- <b:property name="defaultTargetUrl" value="/index.do"></b:property>
- </b:bean>
- <b:bean id="simpleUrlAuthenticationFailureHandler"
- class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
- <b:property name="defaultFailureUrl" value="/login.jsp?login_error=1"></b:property>
- </b:bean>
- public class ValidateCodeAuthenticationFilter extends
- UsernamePasswordAuthenticationFilter {
- private boolean postOnly = true;
- private boolean allowEmptyValidateCode = false;
- private String sessionvalidateCodeField = DEFAULT_SESSION_VALIDATE_CODE_FIELD;
- private String validateCodeParameter = DEFAULT_VALIDATE_CODE_PARAMETER;
- public static final String DEFAULT_SESSION_VALIDATE_CODE_FIELD = "validateCode";
- public static final String DEFAULT_VALIDATE_CODE_PARAMETER = "validateCode";
- public static final String VALIDATE_CODE_FAILED_MSG_KEY = "validateCode.notEquals";
- @Override
- public Authentication attemptAuthentication(HttpServletRequest request,
- HttpServletResponse response) throws AuthenticationException {
- if (postOnly && !request.getMethod().equals("POST")) {
- throw new AuthenticationServiceException(
- "Authentication method not supported: "
- + request.getMethod());
- }
- String username = StringUtils.trimToEmpty(obtainUsername(request));
- String password = obtainPassword(request);
- if (password == null) {
- password = StringUtils.EMPTY;
- }
- UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
- username, password);
- // Place the last username attempted into HttpSession for views
- HttpSession session = request.getSession(false);
- if (session != null || getAllowSessionCreation()) {
- request.getSession().setAttribute(
- SPRING_SECURITY_LAST_USERNAME_KEY,
- TextEscapeUtils.escapeEntities(username));
- }
- // Allow subclasses to set the "details" property
- setDetails(request, authRequest);
- // check validate code
- if (!isAllowEmptyValidateCode())
- checkValidateCode(request);
- return this.getAuthenticationManager().authenticate(authRequest);
- }
- /**
- *
- * <li>比较session中的验证码和用户输入的验证码是否相等</li>
- *
- */
- protected void checkValidateCode(HttpServletRequest request) {
- String sessionValidateCode = obtainSessionValidateCode(request);
- String validateCodeParameter = obtainValidateCodeParameter(request);
- if (StringUtils.isEmpty(validateCodeParameter)
- || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
- throw new AuthenticationServiceException(
- messages.getMessage(VALIDATE_CODE_FAILED_MSG_KEY));
- }
- }
- private String obtainValidateCodeParameter(HttpServletRequest request) {
- return request.getParameter(validateCodeParameter);
- }
- protected String obtainSessionValidateCode(HttpServletRequest request) {
- Object obj = request.getSession()
- .getAttribute(sessionvalidateCodeField);
- return null == obj ? "" : obj.toString();
- }
- public boolean isPostOnly() {
- return postOnly;
- }
- @Override
- public void setPostOnly(boolean postOnly) {
- this.postOnly = postOnly;
- }
- public String getValidateCodeName() {
- return sessionvalidateCodeField;
- }
- public void setValidateCodeName(String validateCodeName) {
- this.sessionvalidateCodeField = validateCodeName;
- }
- public boolean isAllowEmptyValidateCode() {
- return allowEmptyValidateCode;
- }
- public void setAllowEmptyValidateCode(boolean allowEmptyValidateCode) {
- this.allowEmptyValidateCode = allowEmptyValidateCode;
- }
- }
使用SpringSecurity3用户验证(异常信息,验证码)的更多相关文章
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)
系列目录 前言: WebAPI主要开放数据给手机APP,其他需要得知数据的系统,或者软件应用,所以移动端与系统的数据源往往是相通的. Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能, ...
- ASP.NET MVC 5 WEB API 用户验证
参考博客:ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1) 参考博客:MVC WebApi 用户验证 (2)构建ASP.NET MVC5+E ...
- Log4Net在MVC下的配置以及运用线程队列记录异常信息
Log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等),日志就是程序的黑匣子,可以通过日志查看系统的运行过程,从而发现系统的问题.日志的作用:将运 ...
- 模拟用户登录,内含验证码验证和request等操作
模拟用户登录,内含验证码验证和jsp等操作 1.案例需求: 1. 访问带有验证码的登录页面login.jsp 2. 用户输入用户名,密码以及验证码. * 如果用户名和密码输入有误,跳转登录页面,提示: ...
- Django电商项目---完成登录验证和用户中心(个人信息)day3
登录验证的实现 背景说明: 用户在商品界面选择商品后,在点击购物车或者结算订单之前 需要完成用户的登录验证,这里用装饰器来完成 创建装饰器类: df_user/user_decorator.py ...
- Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息
</pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...
- Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息
Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...
- asp.ne如何使用javascript去验证客户端信息,如果验证成功则送往服务器端处理,否则在客户端提示用户(不返回到服务器端处理)
一.问题 在网站一般都有很多地方需要用户去填写一些信息,然后用户点击提交,将信息送往后台储存到数据库中.在这一个过程我以前做法直接在button的click事件中来判断用户输入的数据是否完整和合法,虽 ...
- Android 后台发送邮件 (收集应用异常信息+Demo代码)
上一次说了如何收集我们已经发布的应用程序的错误信息,方便我们调试完善程序.上次说的收集方法主要是把收集的信息通过Http的post请求把相关的异常信息变成请求参数发送到服务器.这个对做过web开发的人 ...
随机推荐
- SNS
SNS,专指社交网络服务.也指社交现有已成熟普及的信息载体,如短信SMS服务.SNS的另一种常用解释:全称Social Network Site,即“社交网站”或“社交网”.SNS也指Social N ...
- On the first day here
记录一下到这里的第一天 简单的自我介绍一下: 姓名: 郑超杰 昵称: 蝴蝶 English Nickname: developerbfl 技能: OC H5 Swift ...
- JS 阻止整个网页的内容被选中
pretty-girl { -webkit-user-select: none; } 可是!可是!不是每个浏览器都可以不忧桑!!!那就只能请脚本大王出山了. 阻止选中 有时候,我们需要禁止用户选中一些 ...
- L2-001. 紧急救援
L2-001. 紧急救援 题目链接:https://www.patest.cn/contests/gplt/L2-001 Dijstra 本题是dijstra的拓展,在求最短路的同时,增加了不同的最短 ...
- 使用JavaScript把页面上的表格导出为Excel文件
如果在页面上展示了一个数据表格,而用户想把这个表格导出为Excel文件,那么在要求不高的情况下,可以不通过服务器生成表格,而是直接利用JavaScript的Blob和Object URL特性将表格导出 ...
- 第六十九节,css入门基础
css入门基础 学习要点: 1.使用CSS 2.三种方式 3.层叠和继承 本章主要探讨HTML5中CSS (层叠样式表),它是用来对HTML文档外观的表现形式进行排版和格式化. 一 使用CSS CSS ...
- 《JS权威指南学习总结--9.1 类和模板》
内容要点: 一.JS类 在JS中,类的所有实例对象都从同一个原型对象上继承属性.因此,原型对象是类的核心.在例6.1 原型中定义了inherit()函数(通过原型继承创建一个新对象),这个函数返回一个 ...
- 使用 Spark MLlib 做 K-means 聚类分析[转]
原文地址:https://www.ibm.com/developerworks/cn/opensource/os-cn-spark-practice4/ 引言 提起机器学习 (Machine Lear ...
- linux mysql-server和mysql-client
我认为server和client是DBMS的两个面向不同操作对象的工具.server是DBMS面向物理层次,包含存储数据的一系列机制.处理方法的集成:client是DBMS面向用户,提供一系列工具为用 ...
- js技巧之this,call,apply
具体到实际应用中,this的指向又可以分为以下四种: 作为对象的方法调用 作为普通函数调用 构造器调用 apply和call调用 接下来我们去剖析前3点,至于第4点的apply和call调用,会在ca ...