Spring Security教程 ---- 验证码功能的实现
有三中方法可以实现验证码的功能
第一种是自定义一个filter,放在SpringSecurity过滤器之前,在用户登录的时候会先经过这个filter,然后在这个filter中实现对验证码进行验证的功能,这种方法不推荐,因为它已经脱离了SpringSecurity
第二种是自定义一个filter让它继承自UsernamePasswordAuthenticationFilter,然后重写attemptAuthentication方法在这个方法中实现验证码的功能,如果验证码错误就抛出一个继承自AuthenticationException的验证吗错误的异常比如(CaptchaException),然后这个异常就会被SpringSecurity捕获到并将异常信息返回到前台,这种实现起来比较简单
- @Override
- public Authentication attemptAuthentication(HttpServletRequest request,
- HttpServletResponse response) throws AuthenticationException {
- String requestCaptcha = request.getParameter(this.getCaptchaFieldName());
- String genCaptcha = (String)request.getSession().getAttribute("code");
- logger.info("开始校验验证码,生成的验证码为:"+genCaptcha+" ,输入的验证码为:"+requestCaptcha);
- if( !genCaptcha.equals(requestCaptcha)){
- throw new CaptchaException(
- this.messageSource.getMessage("AbstractUserDetailsAuthenticationProvider.badCaptcha",null,"Default",null));
- }
- return super.attemptAuthentication(request, response);
- }
然后在配置文件中配置下
- <bean id="loginFilter" class="com.zrhis.system.security.DefaultUsernamePasswordAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"></property>
- <property name="authenticationSuccessHandler">
- <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
- <property name="defaultTargetUrl" value="/index.jsp"></property>
- </bean>
- </property>
- <property name="authenticationFailureHandler">
- <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
- <property name="defaultFailureUrl" value="/login.jsp"></property>
- </bean>
- </property>
- </bean>
最后在http中加入custom-filter配置,将这个filter放在SpringSecurity的FORM_LOGIN_FILTER之前
- <custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER"/>
最后一种是直接替换掉SpringSecurity的UsernamePasswordAuthenticationFilter,这种比较复杂,但是更为合理,也是我现在正在用的。
如果用这种方法那么http 中的auto-config就必须去掉,而form-login配置也必须去掉,因为这个不需要了,里面的属性都需要我们自行注入。
首先需要创建一个EntryPoint
- <bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
- <property name="loginFormUrl" value="/login.jsp" />
- </bean>
然后在http中配置下
- <sec:http access-decision-manager-ref="accessDecisionManager"
- entry-point-ref="authenticationEntryPoint">
然后我们来写CaptchaAuthenticationFilter,同样需要继承自UsernamePasswordAuthenticationFilter
- public class CaptchaAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
- public static final String SPRING_SECURITY_FORM_CAPTCHA_KEY = "j_captcha";
- public static final String SESSION_GENERATED_CAPTCHA_KEY = Constant.SESSION_GENERATED_CAPTCHA_KEY;
- private String captchaParameter = SPRING_SECURITY_FORM_CAPTCHA_KEY;
- public Authentication attemptAuthentication(HttpServletRequest request,
- HttpServletResponse response) throws AuthenticationException {
- String genCode = this.obtainGeneratedCaptcha(request);
- String inputCode = this.obtainCaptcha(request);
- if(genCode == null)
- throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaInvalid"));
- if(!genCode.equalsIgnoreCase(inputCode)){
- throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaNotEquals"));
- }
- return super.attemptAuthentication(request, response);
- }
- protected String obtainCaptcha(HttpServletRequest request){
- return request.getParameter(this.captchaParameter);
- }
- protected String obtainGeneratedCaptcha (HttpServletRequest request){
- return (String)request.getSession().getAttribute(SESSION_GENERATED_CAPTCHA_KEY);
- }
- }
在配置文件中配置CaptchaAuthenticationFilter
- <bean id="captchaAuthenticaionFilter" class="com.zrhis.system.security.CaptchaAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager" />
- <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
- <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
- <property name="filterProcessesUrl" value="/login.do" />
- </bean>
- <bean id="authenticationSuccessHandler" class="com.zrhis.system.security.SimpleLoginSuccessHandler">
- <property name="defaultTargetUrl" value="/WEB-INF/app.jsp"></property>
- <property name="forwardToDestination" value="true"></property>
- </bean>
- <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
- <property name="defaultFailureUrl" value="/login.jsp" />
- </bean>
从配置文件中就可以看出来authenticationManager、authenticationFailureHandler、authenticationSuccessHandler、filterProcessesUrl等都需要我们自行注入了。
filterProcessesUrl定义的是登录验证的地址,默认的是j_spring_security_check这里我们改成login.do
authenticationSuccessHandler中的defaultTargetUrl定义的是登录成功后跳转到的页面
authenticationFailureHandler中的defaultTargetUrl定义的是登录失败后跳转到的页面
我们的首页app.jsp在/WEB-INF下所以需要使用服务器跳转,所以需要将forwardToDestination设为true,因为客户端跳转是不能直接访问WEB-INF下的内容的。
最后在http中将FORM_LOGIN_FILTER替换掉,最终http中完整的配置就变成了下面的内容
- <sec:http access-decision-manager-ref="accessDecisionManager"
- entry-point-ref="authenticationEntryPoint">
- <sec:access-denied-handler ref="accessDeniedHandler"/>
- <sec:session-management invalid-session-url="/login.jsp" />
- <sec:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
- <sec:custom-filter ref="captchaAuthenticaionFilter" position="FORM_LOGIN_FILTER"/>
- </sec:http>
custom-filter中before是在这个filter之前,after是之后,position是替换。
这样就可以实现对验证码的验证了,效果如下
Spring Security教程 ---- 验证码功能的实现的更多相关文章
- Spring Security教程(五):自定义过滤器从数据库从获取资源信息
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- 临远的spring security教程
为啥选择Spring Security 欢迎阅读咱们写的Spring Security教程,咱们既不想写一个简单的入门教程,也不想翻译已有的国外教程.咱们这个教程就是建立在咱们自己做的OA的基础上,一 ...
- Spring Security 教程 大牛的教程
https://www.iteye.com/blog/elim-2247073 Spring Security 教程 Spring Security(20)——整合Cas Spring Securit ...
- Spring Security教程(八):用户认证流程源码详解
本篇文章主要围绕下面几个问题来深入源码: 用户认证流程 认证结果如何在多个请求之间共享 获取认证用户信息 一.用户认证流程 上节中提到Spring Security核心就是一系列的过滤器链,当一个请求 ...
- Spring Security教程(三):自定义表结构
在上一篇博客中讲解了用Spring Security自带的默认数据库存储用户和权限的数据,但是Spring Security默认提供的表结构太过简单了,其实就算默认提供的表结构很复杂,也不一定能满足项 ...
- Spring Security教程(二):通过数据库获得用户权限信息
上一篇博客中,Spring Security教程(一):初识Spring Security,我把用户信息和权限信息放到了xml文件中,这是为了演示如何使用最小的配置就可以使用Spring Securi ...
- [转载]spring security 的 logout 功能
原文地址:security 的 logout 功能">spring security 的 logout 功能作者:sumnny 转载自:http://lengyun3566.iteye ...
- Spring Security教程(三)
在上一篇博客中讲解了用Spring Security自带的默认数据库存储用户和权限的数据,但是Spring Security默认提供的表结构太过简单了,其实就算默认提供的表结构很复杂,也不一定能满足项 ...
- Spring Security教程(二)
上一篇博客中,Spring Security教程(一),我把用户信息和权限信息放到了xml文件中,这是为了演示如何使用最小的配置就可以使用Spring Security,而实际开发中,用户信息和权限信 ...
随机推荐
- typedef可以成为你的朋友
typedef static char int8;这个声明正确吗? A:err 所以上面那个声明是错误的. typedef为一种类型引入新的名字,而不是为变量分配空间,它并没有引入新的类型,而是为现有 ...
- Jquery学习笔记(5)--jquery1.6中的.prop()和.attr()异同
jquery1.6中的.prop()和.attr()异同 最近在iteye的新闻中看到jQuery已经更新到了1.6.1.和之前版本的最大变化是增加了.prop方法.但是.prop()方法和.attr ...
- Unity5.1 新的网络引擎UNET(四) UNET Remote Actions
孙广东 2015.7.12 网络系统 具有网络中执行操作actions 的方法.这些类型的actions 有时是调用远程过程调用(Remote Procedure Calls). 在网络系统中有两 ...
- Unix系统编程(二)open的练习
在上一篇中学习了一下open函数的基本用法,这里就要练习一下.计算机就是要实践嘛. 用open创建一个文件 #include <sys/types.h> #include <sys/ ...
- ARM与X86架构的对决[整编]
CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法.早期的CPU全部是CISC架构,它的设计目的是 CISC要用最少的机器语言 ...
- js删除数组中某一项,splice()
' ","childTagName":"高中"}, {","childTagName":"初中"}] ...
- 海康网络摄像机调用SDK解码Java版
两个回调函数: FRealDataCallBack 实现预览回调数据 DecCallBack 解码回调函数 在HCNetSDK.java补充相关函数和结构声明 //播放库函数声明,PlayCtrl.d ...
- 02 SQL 执行
sql 被保存在 share pool 后, 开始解析, 解析包括语句的语法, 检验及对象, 以确认该用于是否有该对象的权限, 如果这些都通过了, 接下来就要看这个语句之前是否被执行过, 如果是, o ...
- Docker 和一个正常的虚拟机有何区别?
问: 我多次重读Docker.io文档,希望搞明白Docker.io和一个完全的虚拟机的区别.Docker是如何做到提供一个完整的文件系统,独立的网络环境等等这些功能,同时还没有如此庞大? 为什么部署 ...
- Vector、ArrayList、List使用深入剖析
线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以 ...