- 浏览: 94960 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
former:
neebe 写道楼主,能否提供完整的代码,这对我们新手而言,有 ...
在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 2107项目背景 从08年开始 ... -
对Hibernate Session做一个简单的包装
2010-05-27 11:48 1257在谈包装之前,我们先看一看以下几个论断: 牛人们都说da ... -
spring3.0 rest在resin中的实现
2010-05-21 11:36 2690spring3.0发布后,其web方面一个很大的特性是支持re ... -
在Eclipse中使用resin调试maven war项目
2010-05-21 10:55 7065公司现在使用无版权问题的Eclipse环境,同时希望将目前手工 ... -
xml rpc with sping beans
2008-08-03 21:29 2296最近在处理web services时 ... -
Ehcache定时刷新
2007-04-20 11:22 12306之前的文章介绍了在项目里使用Ehcache的经历,现在它可以很 ... -
使用EhCache1.1与Hibernate所吃的亏
2007-03-27 14:18 7608“偶们的系统越来越慢了!”,这是最近一直在我耳边萦绕的一句话, ... -
Eclipse里exadel studio pro与其他工具的冲突
2007-03-16 10:34 2953在之前的文章中写道exadel现在与jboss合作,旗下的ex ... -
自己做的Ajax4Jsf 的几个小例子
2007-03-09 16:57 9825JSF好像充满了争议,被很多Java大牛们所抱怨,而很多主流厂 ... -
exadel与jboss合作开源
2007-03-06 10:51 1796ajax4jsf选择与jboss合作开源了,详细链接 http ...
相关推荐
在spring-boot-security的基础上实现角色管理。 spring-boot-security-jwt实现动态角色管理,并集成JWT以token代替session。此版本未实现验证码登录的功能。 登录认证方式和spring-boot-security有所不同。该版本...
主要介绍了Spring Security OAuth2集成短信验证码登录以及第三方登录,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
NULL 博文链接:https://jw-long.iteye.com/blog/1291866
实现spring-gateway登录验证码校验,使用randomstr参数作为每次生成验证码图片的唯一标识,验证码Kaptcha插件
本篇文章主要介绍了Spring Security Oauth2.0 实现短信验证码登录示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
主要介绍了Spring Security 实现短信验证码登录功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
Spring Security 默认是账号和密码登录,现在是对 Spring Security 进行扩展,来实现短信验证码方式登录。 SpringBoot 集成 Spring Security短信验证码登录【完整源码+数据库】
主要介绍了Spring Security实现验证码登录功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Springboot集成spring-security实现基于验证码的登录认证项目_源码
springsecurity3和JCaptcha的整合 验证码
项目中使用到的技术包含SpringBoot、SpringSecurity&oauth2(安全资源和授权中心模式、包括登录接口自定义返回字段、自定义手机号+密码登录、自定义免密登录)、Queue队列、线程池、xss攻击配置、SpringCache、Mybatis...
spring security 实现动态权限和短信验证码登录,整合了jwt和redis来实现动态权限管理
主要介绍了SpringBoot + SpringSecurity 实现图形验证码功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了SpringBoot + SpringSecurity 短信验证码登录功能实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
struts2+spring3验证码登录实例,其中包括实现实例所包含的所有包。环境:win7+myeclipse2013+tomcat7.0
springsecurity验证码登录.
spring mvc + spring security + 自定义form表单+验证码+bootstrap
集成 spring securit, spring security oauth 和 spring social,实现 用户名密码登录,手机验证码登录,社交账号登录,基于jwt的sso,集群session管理等功能。
主要介绍了Spring Security登录添加验证码的实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
SpringSecurity实现表单安全登录、图形验证的校验、记住我时长控制机制、第三方登录