- 浏览: 96511 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
former:
<div class="quote_title ...
在spring security3上实现验证码 -
neebe:
楼主,能否提供完整的代码,这对我们新手而言,有点无头无绪的感觉 ...
在spring security3上实现验证码 -
bin_1715575332:
运行前需要添加什么东西么,能否提供和联系方式?请求一下
在Eclipse中使用resin调试maven war项目 -
bin_1715575332:
还是有点不太懂。。。
在Eclipse中使用resin调试maven war项目 -
former:
crazoy 写道这点我非常认同。比如有的求职者会写“精通Ja ...
《软件人才管理的艺术》中的看简历的技巧
关于验证码的实现
验证码的例子现在多如牛毛,大家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);
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")); } }
这里有几点想说明一下:
- 这里使用messages,符合上文中我们说直接利用SS3中的基础构建。
- 当校验出错时,抛出AuthenticationServiceException异常,这里其实大家可以自定义一个异常类,继承AuthenticationException即可。抛出这个异常后,父类中的代码会为我们处理这个异常,让我们享受一下继承的优势。
- 之所以在Filter中校验验证码是因为之类有我们需要的web接口,实现更加方便。
2.配置自定义的UsernamePasswordAuthenticationFilter
替换<form-login>
原有在<http>中的<form-login>肯定是不能在用了,我们使用一个<custom-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>
相应的,<http>也需要做点修改:
<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>
注意一下这里的"authenticationManager"属性,在NamingSpace的默认配置里,我们不需要特别指定这个属性,SS3会为我们找到<authentication-manager>。此时,我们需要给<authentication-manager>配置一个别名:
<authentication-manager alias="authenticationManager">
做点优化
从配置文件中,我们看到登录链接被引用了多次,我们可以将其写在一个.properties文件中,并在xml中引用。
到此,一切事物准备就绪,验证码可以正常工作了。
后记
我从08年起,利用Acegi1.0.6构建公司内多系统见的认证、授权功能,当时没有NamingSpace,有的只是一个针对请求的拦截器链和Spring beans,虽然繁琐,但是清晰、明了。顺着这个链走下去,让你了解什么认证、授权工作的步骤及其内因,例如著名的投票策略。多年以后再回首,曾经的Acegi,摇身一变成了Spring Security,丰富了很多的功能,文档也做了很多的改进,但是也像他的亲爹Spring一样,穿上了一件又一件的花衣服,NamingSpace是很酷,但也增加了一个初学者了解其内里的难度。
- code.rar (2.4 KB)
- 下载次数: 1537
评论
谢谢了
附件是有源码下载的呀
谢谢了
<div class="quote_div">轻轻地问一下,你这验证码错了,你怎么在前台给用户提示呢</div>
<p>easy,看下父类AbstractAuthenticationProcessingFilter里面的unsuccessfulAuthentication:</p>
<pre name="code" class="java"> protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
SecurityContextHolder.clearContext();
if (logger.isDebugEnabled()) {
logger.debug("Authentication request failed: " + failed.toString());
logger.debug("Updated SecurityContextHolder to contain null Authentication");
logger.debug("Delegating to authentication failure handler" + failureHandler);
}
HttpSession session = request.getSession(false);
if (session != null || allowSessionCreation) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed);
}
rememberMeServices.loginFail(request, response);
failureHandler.onAuthenticationFailure(request, response, failed);
}</pre>
<p> </p>
<p>我们在校验验证码的时候抛出的异常被丢到了Session中,这样你可以在页面上拿到异常信息,辅助message的本地化处理或者不同的异常子类,你可以告诉用户他错在哪了。</p>
毕竟事情还是那个事……
......
Spring是一个非常灵活的框架,而Spring Security却如此霸王。在一定程度上,这样的设计的确可以避免很多由于Filter次序配置的混乱造成的问题,然而却失去了灵活性。可谓是得不偿失。
虽然想说:“不用namespace,直接用原来那种acegi的配置方式就行了。”但是这样说明显是在强词夺理。
言归正传,namespace不怎么灵活,如果在它上面进行扩展,除了user-details-service,authentication-provider那种已经留好的扩展点,要改其他的东西都必须看源代码,搞明白了里边的运行结构才能动刀子。从这点来看,spring security还很不成熟。
原来定制Acegi的拦截器链也没觉得太混乱,还是挺清晰的。现在看到命名空间整的这么花哨,让我怀疑是不是这波是不是想靠培训挣点钱啊……
namespace最大的功劳是降低了新手的入门门槛,相比acegi需要几百行代码才能完成Hello world,namespace只需要10几行xml就ok了。花俏也是迫不得已的,过于复杂的配置让开发和维护都步履维艰,为啥不让修改几个默认的过滤?还不是因为acegi时代总是有人配置错误。
实际上,spring security除了支持namespace以外,像你这样的老手依然可以使用acegi那种超复杂的方式进行配置,不要导入springsecurity-config包就行了。
提供的命名空间的定制在一定程度上简化了acegi的配置,定制起来还是有点麻烦,为了使用3.0版本的security,源码阅读了一部分才搞明白!
......
Spring是一个非常灵活的框架,而Spring Security却如此霸王。在一定程度上,这样的设计的确可以避免很多由于Filter次序配置的混乱造成的问题,然而却失去了灵活性。可谓是得不偿失。
虽然想说:“不用namespace,直接用原来那种acegi的配置方式就行了。”但是这样说明显是在强词夺理。
言归正传,namespace不怎么灵活,如果在它上面进行扩展,除了user-details-service,authentication-provider那种已经留好的扩展点,要改其他的东西都必须看源代码,搞明白了里边的运行结构才能动刀子。从这点来看,spring security还很不成熟。
原来定制Acegi的拦截器链也没觉得太混乱,还是挺清晰的。现在看到命名空间整的这么花哨,让我怀疑是不是这波是不是想靠培训挣点钱啊……
namespace最大的功劳是降低了新手的入门门槛,相比acegi需要几百行代码才能完成Hello world,namespace只需要10几行xml就ok了。花俏也是迫不得已的,过于复杂的配置让开发和维护都步履维艰,为啥不让修改几个默认的过滤?还不是因为acegi时代总是有人配置错误。
实际上,spring security除了支持namespace以外,像你这样的老手依然可以使用acegi那种超复杂的方式进行配置,不要导入springsecurity-config包就行了。
非常中肯的评价。
我们需要看到的是Spring Security还处于发展的过程中。期待他变得越来越好。
......
Spring是一个非常灵活的框架,而Spring Security却如此霸王。在一定程度上,这样的设计的确可以避免很多由于Filter次序配置的混乱造成的问题,然而却失去了灵活性。可谓是得不偿失。
虽然想说:“不用namespace,直接用原来那种acegi的配置方式就行了。”但是这样说明显是在强词夺理。
言归正传,namespace不怎么灵活,如果在它上面进行扩展,除了user-details-service,authentication-provider那种已经留好的扩展点,要改其他的东西都必须看源代码,搞明白了里边的运行结构才能动刀子。从这点来看,spring security还很不成熟。
原来定制Acegi的拦截器链也没觉得太混乱,还是挺清晰的。现在看到命名空间整的这么花哨,让我怀疑是不是这波是不是想靠培训挣点钱啊……
namespace最大的功劳是降低了新手的入门门槛,相比acegi需要几百行代码才能完成Hello world,namespace只需要10几行xml就ok了。花俏也是迫不得已的,过于复杂的配置让开发和维护都步履维艰,为啥不让修改几个默认的过滤?还不是因为acegi时代总是有人配置错误。
实际上,spring security除了支持namespace以外,像你这样的老手依然可以使用acegi那种超复杂的方式进行配置,不要导入springsecurity-config包就行了。
比如说,在其文档中有这么一段:
如果你替换了一个命名空间的过滤器,而这个过滤器需要一个验证入口点(比如,认证过程是通过一个未通过验证的用户访问受保护资源的尝试来触发的),你将也需要添加一个自定义的入口点bean。
而实际上我们知道,FilterSecurityInterceptor这样重要的用于URL等资源校验的Filter,我们往往是要进行扩展的。
Spring是一个非常灵活的框架,而Spring Security却如此霸王。在一定程度上,这样的设计的确可以避免很多由于Filter次序配置的混乱造成的问题,然而却失去了灵活性。可谓是得不偿失。
这段话的确是在文档中,不过你的中文文档在哪啊,我只在官网找到英文的,能给个链接不?
我的例子中已经给了“验证入口点”,觉得实现起来不是太麻烦。当我看到不能替换那段时,我也惊掉了下巴,不过我还没试过。
原来定制Acegi的拦截器链也没觉得太混乱,还是挺清晰的。现在看到命名空间整的这么花哨,让我怀疑是不是这波是不是想靠培训挣点钱啊……
比如说,在其文档中有这么一段:
如果你替换了一个命名空间的过滤器,而这个过滤器需要一个验证入口点(比如,认证过程是通过一个未通过验证的用户访问受保护资源的尝试来触发的),你将也需要添加一个自定义的入口点bean。
而实际上我们知道,FilterSecurityInterceptor这样重要的用于URL等资源校验的Filter,我们往往是要进行扩展的。
Spring是一个非常灵活的框架,而Spring Security却如此霸王。在一定程度上,这样的设计的确可以避免很多由于Filter次序配置的混乱造成的问题,然而却失去了灵活性。可谓是得不偿失。
发表评论
-
在多数据源(JTA)环境下使用Spring TestContext Framework
2010-08-09 10:26 2235项目背景 从08年开始 ... -
对Hibernate Session做一个简单的包装
2010-05-27 11:48 1295在谈包装之前,我们先看一看以下几个论断: 牛人们都说da ... -
spring3.0 rest在resin中的实现
2010-05-21 11:36 2740spring3.0发布后,其web方面一个很大的特性是支持re ... -
在Eclipse中使用resin调试maven war项目
2010-05-21 10:55 7107公司现在使用无版权问题的Eclipse环境,同时希望将目前手工 ... -
xml rpc with sping beans
2008-08-03 21:29 2394最近在处理web services时 ... -
Ehcache定时刷新
2007-04-20 11:22 12406之前的文章介绍了在项目里使用Ehcache的经历,现在它可以很 ... -
使用EhCache1.1与Hibernate所吃的亏
2007-03-27 14:18 7689“偶们的系统越来越慢了!”,这是最近一直在我耳边萦绕的一句话, ... -
Eclipse里exadel studio pro与其他工具的冲突
2007-03-16 10:34 2985在之前的文章中写道exadel现在与jboss合作,旗下的ex ... -
自己做的Ajax4Jsf 的几个小例子
2007-03-09 16:57 9857JSF好像充满了争议,被很多Java大牛们所抱怨,而很多主流厂 ... -
exadel与jboss合作开源
2007-03-06 10:51 1860ajax4jsf选择与jboss合作开源了,详细链接 http ...
相关推荐
在本文中,我们将深入探讨如何在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 短信验证码登录功能实现的详细过程,该功能可以使用户通过手机短信验证码登录系统,而不是传统的用户名密码登录...