- 浏览: 1336342 次
- 性别:
- 来自: 成都
文章分类
- 全部博客 (471)
- 原创文章 (4)
- Database (84)
- J2SE (63)
- Web (26)
- Javascript (30)
- Lucene (11)
- os (13)
- 算法 (8)
- Webservice (1)
- Open projects (18)
- Hibernate (18)
- Spring (15)
- Css (2)
- J2ee (2)
- 综合技术 (18)
- 安全管理 (13)
- PatternsInJava (27)
- NIO (5)
- Ibatis (2)
- 书籍收藏 (1)
- quartz (7)
- 并发编程 (15)
- oracle问题 (2)
- ios (60)
- coco2d-iphone (3)
- C++ (6)
- Zookeeper (2)
- golang (4)
- animation (2)
- android (1)
最新评论
-
dandingge123:
【引用】限制UITextField输入长度的方法 -
qja:
...
对List顺序,逆序,随机排列实例代码 -
安静听歌:
现在在搞这个,,,,,哎~头都大了,,,又freemarker ...
通用大型网站页面静态化解决方案(一) -
springdata-jpa:
java quartz定时任务demo教程源代码下载,地址:h ...
Quartz 配置参考 -
马清天:
[b][/b][list][*]引用[u][/u][/list ...
通用大型网站页面静态化解决方案(一)
关于验证码的实现
验证码的例子现在多如牛毛,大家google一下就有很多,通常的做法是在session中生成一个随机串,再由用户提交到server端去验证。因为最近在看SS3,所以这里主要想讲验证码与SS3的结合。
验证码与SS3结合的实现方案
方案一:自己写个filter
严格来讲,这不是与SS3结合,而只是在项目中实现一个filter,然后将其拦截次序放在SS3的filter前面即可。这样做的好处是简单且通 用,以后不玩SS3了,也可以使用。缺点也很明显,那就是在SS3中配置的一应事物都要重新配置,例如拦截的URL、失败的URL、报错的资源文件、异常 后的重定向设置等等。
方案二:定制一个新的SS3的filter
通过在<http>中声明一个<custom-filter>,设置其"before"属性,让它 在"FORM_LOGIN_FILTER"前作拦截即可。这样做看上去更集中、直观,对SS3的<http>元素的默认设置改变也很小,但是 和方法一相似,还是要配置很多事物,写很多的基础代码。
方案三:扩展UsernamePasswordAuthenticationFilter
改方案通过继承UsernamePasswordAuthenticationFilter,并重载attemptAuthentication方 法,在其中增加校验验证码的逻辑。其优点是省去了编写上文中说的基础代码,相关的URL、资源文件的配置只要再此filter中配置一次即可;其缺点就是 将其插入到已有的NamingSpace声明的拦截器链中非常麻烦。我们要理解NamingSpace的配置信息、理解拦截器的顺序、别名、作用,以及要 深入SS3的源码,看UsernamePasswordAuthenticationFilter的源码,了解它及其父类中有哪些属性是必须配置或我们需 要重新配置的。
虽然这种方法烦了一点,但是我最终还是选择了此方法。因为其难度是建立于理解SS3之上的,而其好处也显而易见。
实现步骤
1.自定义UsernamePasswordAuthenticationFilter
这一步还是很简单的,我们声明一个类:ValidateCodeUsernamePasswordAuthenticationFilter,它继 承UsernamePasswordAuthenticationFilter,并重载attemptAuthentication方法,增加校验验证码 码的逻辑。这里要稍稍抗议一下SS3的作者们,那个"postOnly"属性为什么不写个读方法呢……以前在扩展Acegi的时候也遇到过类似的情况某个 私有成员变量没有读方法而被迫重写了大段的代码,虽然很多事copy的……
来看一下attemAuthentication的代码片段:
- if (!isAllowEmptyValidateCode())
- checkValidateCode(request);
- return this .getAuthenticationManager().authenticate(authRequest);
if (!isAllowEmptyValidateCode()) checkValidateCode(request); return this.getAuthenticationManager().authenticate(authRequest);
checkValidateCode也很简单:
- 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( "validateCode.notEquals" ));
- }
- }
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("validateCode.notEquals")); } }
这里有几点想说明一下:
- 这里使用messages,符合上文中我们说直接利用SS3中的基础构建。
- 当校验出错时,抛出AuthenticationServiceException异常,这里其实大家可以自定义一个异常类,继承AuthenticationException即可。抛出这个异常后,父类中的代码会为我们处理这个异常,让我们享受一下继承的优势。
- 之所以在Filter中校验验证码是因为之类有我们需要的web接口,实现更加方便。
2.配置自定义的UsernamePasswordAuthenticationFilter
替换<form-login>
原有在<http>中的<form-login>肯定是不能在用了,我们使用一个<custom-filter>来替换:
- <custom-filter ref= "validateCodeAuthenticationFilter" position= "FORM_LOGIN_FILTER" />
<custom-filter ref="validateCodeAuthenticationFilter" position="FORM_LOGIN_FILTER" />
position表示我们替换了原来别名"FORM_LOGIN_FILTER"所标示的 类:UsernamePasswordAuthenticationFilter。但事情并非这么简单,通过阅读SS3的手册2.3、5.4节,我们得知 还需要一个AuthenticationEntryPoint:
- < beans:bean id = "authenticationProcessingFilterEntryPoint"
- class = "org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint" >
- < beans:property name = "loginFormUrl" value = "/login" > </ beans:property >
- </ beans:bean >
<beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint"> <beans:property name="loginFormUrl" value="/login"></beans:property> </beans:bean>
相应的,<http>也需要做点修改:
- < http use-expressions = "true" entry-point-ref = "authenticationProcessingFilterEntryPoint" >
<http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">
配置ValidateCodeUsernamePasswordAuthenticationFilter
配置ValidateCodeUsernamePasswordAuthenticationFilter时,我们需要将所需的属性配置完全,包括 认证成功、失败的处理器。这里多出来的配置,主要是在bean上,而bean中需要的属性,如认证过滤URL、认证成功URL、认证失败URL 在<form-login>中也是需要配置的,所以我们的工作并不多:
- < beans:bean id = "validateCodeAuthenticationFilter"
- class = "com.cloudframework.extend.spring.security.web.authentication.ValidateCodeUsernamePasswordAuthenticationFilter" >
- < beans:property name = "filterProcessesUrl" value = "/logon" > </ beans:property >
- < beans:property name = "authenticationSuccessHandler"
- ref = "loginLogAuthenticationSuccessHandler" > </ beans:property >
- < beans:property name = "authenticationFailureHandler"
- ref = "simpleUrlAuthenticationFailureHandler" > </ beans:property >
- < beans:property name = "authenticationManager" ref = "authenticationManager" > </ beans:property >
- </ beans:bean >
- < beans:bean id = "loginLogAuthenticationSuccessHandler"
- class = "org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler" >
- < beans:property name = "defaultTargetUrl" value = "/main" > </ beans:property >
- </ beans:bean >
- < beans:bean id = "simpleUrlAuthenticationFailureHandler"
- class = "org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" >
- < beans:property name = "defaultFailureUrl" value = "/login" > </ beans:property >
- </ beans:bean >
<beans:bean id="validateCodeAuthenticationFilter" class="com.cloudframework.extend.spring.security.web.authentication.ValidateCodeUsernamePasswordAuthenticationFilter"> <beans:property name="filterProcessesUrl" value="/logon"></beans:property> <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property> <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property> <beans:property name="authenticationManager" ref="authenticationManager"></beans:property> </beans:bean> <beans:bean id="loginLogAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/main"></beans:property> </beans:bean> <beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login"></beans:property> </beans:bean>
注意一下这里的"authenticationManager"属性,在NamingSpace的默认配置里,我们不需要特别指定这个属 性,SS3会为我们找到<authentication-manager>。此时,我们需要给<authentication- manager>配置一个别名:
- < authentication-manager alias = "authenticationManager" >
<authentication-manager alias="authenticationManager">
做点优化
从配置文件中,我们看到登录链接被引用了多次,我们可以将其写在一个.properties文件中,并在xml中引用。
到此,一切事物准备就绪,验证码可以正常工作了。
后记
我从08年起,利用Acegi1.0.6构建公司内多系统见的认证、授权功能,当时没有NamingSpace,有的只是一个针对请求的拦截器链和 Spring beans,虽然繁琐,但是清晰、明了。顺着这个链走下去,让你了解什么认证、授权工作的步骤及其内因,例如著名的投票策略。多年以后再回首,曾经的 Acegi,摇身一变成了Spring Security,丰富了很多的功能,文档也做了很多的改进,但是也像他的亲爹Spring一样,穿上了一件又一件的花衣服,NamingSpace是很 酷,但也增加了一个初学者了解其内里的难度。
评论
<!-- 前台认证管理器 --> <authentication-manager alias="userAuthManager" > <authentication-provider user-service-ref="frontUserDetailsServiceImpl" /> </authentication-manager> <!--后台认证管理器 --> <authentication-manager alias="adminAuthManager"> <authentication-provider user-service-ref="adminDetailsServiceImpl" /> </authentication-manager>
楼主,我遇到了一个问题。我有两张表User和Admin,因此我得写两个UserDetailServiceImpl(FrontUserDetailsServiceImpl和AdminDetailsServiceImpl),按照楼主的方法我也写了两个过滤器(UserAuthenticationFilter.java和AdminAuthenticationFilter.java)分别用于前台和后台的用户验证,过滤器引用了各自的认证管理器authenticationManager(上述代码),但是当我运行起来,发现后台管理员可以登陆成功,前台用户却无法登陆成功,断点之后发现,原来(UserAuthenticationFilter的attemptAuthentication方法每次验证完用户名和密码,return this.getAuthenticationManager().authenticate(authRequest)调用的是AdminDetailsServiceImpl中的loadUserByUsername方法,我把配置文件中的两个认证管理器调换一下位置,让“后台认证管理器”在前,另一个在后,这次是前天用户可以登陆成功,后台管理员无法登陆,感觉是<authentication-manager>只能配置一个,配置多个的话,后一个会把前面配置的都覆盖了,不知道是不是这样子?想了很久不知道如何解决,不知道楼主有什么解决方法?
发表评论
-
aop:aspect
2011-03-31 11:01 5065package com.albert.spring.proxy ... -
spring包详解
2011-01-27 17:15 1364spring.jar是包含有完整发布的单个jar包,sprin ... -
hibernate部分字段更新的解决方案
2010-12-06 16:33 6755在调用Hibernate的update方法时会更新对象的全部字 ... -
spring 读取applicationContext方式
2010-11-26 14:08 3754加载器目前有两种选择:ContextLoaderListene ... -
spring mvc 流程
2010-11-19 10:00 1759对于流程网上有以下解释: 它的处理流程是这样的: g ... -
Acegi Security -- Spring下最优秀的安全系统
2010-11-11 10:12 1993一 Acegi安全系统介 ... -
spring security 同步session控制
2010-11-05 09:50 3556如果你希望限制单个用户只能登录到你的程序一次,Spring ... -
Spring HTTP invoker简介
2010-10-26 21:22 9031核心提示:Spring HTTP invoker简介 Sp ... -
Spring 国际化的支持:Spring MVC Velocity
2010-10-26 21:19 7557核心提示:在Spring的国际化配置中,一共有三种描述方式 ... -
spring 配置多数据源
2010-10-25 20:52 3161Spring2.0.1以后的版本已经支持配置多数据源,并且可以 ... -
Spring多数据源解决方案
2010-10-25 20:29 6641在很多大型应用中都会对数据进行切分,并且采用多个数据库实例进行 ... -
Spring多数据源解决方案(研究,不确信是正确)
2010-10-25 20:25 2793开发目的:一个协同平台项目,多托管用户,单门户系统,每个托管用 ... -
Hibernate 与 Spring 多数据源的配置
2010-10-24 16:45 1652Spring2.0.1以后的版本已经支持配置多数据源,并且可以 ... -
spring javamail
2010-01-07 11:50 3487一直以来都是用javax.mail来写email发送,看了sp ...
相关推荐
在本文中,我们将深入探讨如何在Spring Security 3.1版本中实现验证码的自定义登录,以增强系统安全性,防止恶意自动登录攻击。 首先,验证码是Web应用中防止自动化脚本或机器人恶意操作的一种常见手段。在登录过程...
在实现集成登录认证组件时,我们需要了解OAuth2.0认证体系、SpringBoot、SpringSecurity以及Spring Cloud等相关知识。同时,我们还需要了解如何定义拦截器、如何在拦截的通知进行预处理、如何在UserDetailService....
本教程将详细讲解如何在Spring Boot 3.x版本中结合Spring Security的最新版实现JWT(JSON Web Token)登录验证。 首先,让我们了解JWT。JWT是一种轻量级的身份认证和授权机制,它以JSON对象的形式在客户端和服务器...
在本项目中,我们将探讨如何在 Spring Gateway 中实现登录时的验证码校验功能,确保用户身份的安全性。 验证码是一种防止自动机器人或恶意软件进行非法操作的有效手段,它要求用户输入显示在图像中的随机字符序列。...
在实现短信验证码登录示例时,我们需要注意以下细节: 1. 手机号码登录令牌 MobileAuthenticationToken 需要继承自 AbstractAuthenticationToken 类 2. 手机号码登录校验逻辑 MobileAuthenticationProvider 需要...
在spring-boot-security的基础上实现角色管理。 spring-boot-security-jwt实现动态角色管理,并集成JWT以token代替session。此版本未实现验证码登录的功能。 登录认证方式和spring-boot-security有所不同。该版本...
知识点一:Spring Security验证码登录功能的实现原理 Spring Security的验证码登录功能是基于Java的图形验证码技术实现的。该技术生成一个随机的验证码图片,用户需要输入正确的验证码以完成登录。这样可以防止...
在本文中,我们将深入探讨如何使用Spring Security框架实现短信验证码登录功能。Spring Security是一个强大的安全框架,用于管理和保护Web应用程序的访问控制。在传统的用户名密码登录方式之外,短信验证码登录提供...
在本项目中,我们主要探讨的是如何将Spring Boot与Spring Security进行集成,以构建一个基于验证码的登录认证系统。Spring Boot是Spring框架的简化版本,它提供了快速开发新应用的能力,而Spring Security则是一个...
在本项目中,我们主要探讨的是如何利用Spring MVC和Spring Security框架构建一个基本的无数据库登录系统。Spring MVC是Spring框架的一部分,用于处理Web应用程序的请求-响应模型,而Spring Security则是一个强大的...
在本文中,我们使用了 Spring Boot 结合 Spring Security 来实现图形验证码功能。我们首先创建了一个 ValidateCodeController 来处理图形验证码的生成和验证。在生成图形验证码时,我们使用了 BufferedImage 类来...
2. **手机号登录**:为了适应移动互联网的需求,Spring Security可以通过扩展实现短信验证码或直接使用手机号作为身份验证的凭证。这通常涉及到与短信服务提供商的集成,以及对手机号的验证逻辑。 3. **邮箱登录**...
在本文中,我们将深入探讨如何在Spring Security 3框架中实现用户验证,特别是涉及异常处理和验证码功能。Spring Security是一个强大的安全框架,用于保护Java应用,包括Web应用。以下是对标题和描述中提及知识点的...
Spring Security 默认是账号和密码登录,现在是对 Spring Security 进行扩展,来实现短信验证码方式登录。 SpringBoot 集成 Spring Security短信验证码登录【完整源码+数据库】
这个压缩包“springsecurity验证码登录.rar”显然是为了演示如何在SpringSecurity中集成验证码功能,以增强用户登录的安全性。验证码是防止恶意自动登录尝试(如机器人或脚本)的有效手段,它要求用户在登录时输入...
通过以上介绍,我们可以看到SpringSecurity在实现安全登录和身份验证方面提供了全面的支持。结合图形验证码、记住我功能以及第三方登录的集成,我们可以构建出一套既安全又用户友好的认证系统。在实际项目中,理解并...
在这个场景中,我们探讨的是如何利用Spring Security实现动态权限管理和短信验证码登录,并结合JWT(JSON Web Tokens)和Redis来提升系统的效率和安全性。 首先,让我们深入了解Spring Security的基础。Spring ...
为了在 Spring Security 框架中实现这个功能,我们需要准备验证码和在登录页面中添加验证码输入框。 验证码的生成 验证码的生成是登录添加验证码的实现过程中的第一步。我们可以使用 Java 自画的验证码,使用 `...
springsecurity3和JCaptcha的整合 验证码
SpringBoot + SpringSecurity 短信验证码登录功能实现 本文主要介绍了 SpringBoot + SpringSecurity 短信验证码登录功能实现的详细过程,该功能可以使用户通过手机短信验证码登录系统,而不是传统的用户名密码登录...