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是替换。
这样就可以实现对验证码的验证了,效果如下
最新文章
- MySQL详解--锁
- Javascript技巧
- MYSQL EXPLAIN 很慢的原因
- VB操作Excel
- 一秒钟速算(WINFORM)
- C# WPF 建立渐隐窗口
- Jafka来源分析——Processor
- angular2+webpack的搭建过程遇到的问题记录
- AlloyFinger.js 源码 学习笔记及原理说明
- hdu4027 开方,记录
- Python自学笔记-with详解
- 使用JS实现图片轮播滚动跑马灯效果
- Pandora 生成 Token
- 记一次eureka客户端注册失败的问题
- PL/SQL修改数据之后,程序查到的还是原来的数据怎么办?
- hibernate一级缓存和快照
- 从YOLOv1到YOLOv3,目标检测的进化之路
- 包--json 与 pickle 模块
- learning scala ide tools install
- HTTP的请求报文与响应报文
热门文章
- openssl之BIO系列之18---接受(accept)类型BIO
- shell常用的判断条件
- UITextField小结
- hdu6060 RXD and dividing 贪心
- MapReduce实战(六)共同粉丝
- shiro添加注解@RequiresPermissions无效
- 蓝桥杯 第三届C/C++预赛真题(7) 放棋子(水题)
- Python中xlrd和xlwt模块使用方法 (python对excel文件的操作)
- Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
- label 两次点击 事件冒泡 使用时间戳的解决方案