Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作。我今天要做的是对UsernamePasswordAuthenticationFilter进行扩展,新增一个Filter,完成对登录页面的校验码的验证。下面先给一张过滤器的说明,接下来讲自定义的登录验证Filter。

 https://docs.spring.io/spring-security/site/docs/3.2.8.RELEASE/reference/htmlsingle/#ns-web-advanced

   一、扩展AbstractAuthenticationProcessingFilter,实现MyUsernamePasswordAuthenticationFilter。

package simm.spring.web.config;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.StringUtils; public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
// 是否开启验证码功能
private boolean isOpenValidateCode = true; public static final String VALIDATE_CODE = "validateCode"; public MyUsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/user/login.do", "POST"));
SimpleUrlAuthenticationFailureHandler failedHandler = (SimpleUrlAuthenticationFailureHandler)getFailureHandler();
failedHandler.setDefaultFailureUrl("/user/login.do?validerror");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse)response; if (!requiresAuthentication(req, res)) {
chain.doFilter(request, response);
return;
}
if (isOpenValidateCode) {
if(!checkValidateCode(req, res))return;
}
//保存一些session信息
HttpSession session = req.getSession();
session.setAttribute(VALIDATE_CODE, "mytest");
chain.doFilter(request,response);
} /**
* 覆盖授权验证方法,这里可以做一些自己需要的session设置操作
*/
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
return null;
} protected boolean checkValidateCode(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
HttpSession session = request.getSession(); String sessionValidateCode = obtainSessionValidateCode(session);
sessionValidateCode = "1234";// 做个假的验证码;
// 让上一次的验证码失效
session.setAttribute(VALIDATE_CODE, null);
String validateCodeParameter = obtainValidateCodeParameter(request);
if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
unsuccessfulAuthentication(request, response, new InsufficientAuthenticationException("输入的验证码不正确"));
return false;
}
return true;
} private String obtainValidateCodeParameter(HttpServletRequest request) {
Object obj = request.getParameter(VALIDATE_CODE);
return null == obj ? "" : obj.toString();
} protected String obtainSessionValidateCode(HttpSession session) {
Object obj = session.getAttribute(VALIDATE_CODE);
return null == obj ? "" : obj.toString();
}
}

  代码解读

  1、为Filter指定请求地址过滤器,用于拦截登录请求。调用AbstractAuthenticationProcessingFilter.requiresAuthentication方法。

  2、指定验证失败的跳转页面

  

  3、验证码的测试代码。假的验证码1234,与页面参数比对后,如果不相等则抛出"输入的验证码不正确"的异常。

  

  4、验证通过,继续执行后续的Filter链。否则退出请求处理逻辑。这个Filter只处理验证码的校验逻辑,用户名密码的验证交给后面的UsernamePasswordAuthenticationFilter来处理。

  

   二、向HttpSecurity的Filter链上插入自定义的Filter,插入到UsernamePasswordAuthenticationFilter的位置上。插入方法有addFilterBefore,addFilterAt,addFilterAfter。这个地方需要注意使用addFilterAt并不是说能替换掉原有的Filter,事实上框架原有的Filter在启动HttpSecurity配置的过程中,都由框架完成了其一定程度上固定的配置,是不允许更改替换的。根据测试结果来看,调用addFilterAt方法插入的Filter,会在这个位置上的原有Filter之前执行。

@Override
protected void configure(HttpSecurity http) throws Exception {
String doUrl = "/**/*.do";
http
.addFilterAt(new MyUsernamePasswordAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)

  三、登录方法添加对验证码错误回调的拦截

@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "validerror", required = false) String validerror,
@RequestParam(value = "logout", required = false) String logout,Model model) {
if (error != null) {
model.addAttribute("msg", "用户名或密码错误!");
}
if(validerror!=null){
model.addAttribute("msg", "验证码错误!");
}
if (logout != null) {
model.addAttribute("msg", "成功退出!");
}
return "user/login";
}

     四、测试结果展示

  

  以上就是我对登录功能的自定义Filter实现。其他Filter都是同理,如果需要都可以自行扩展。东西不多,希望对你有所帮助,欢迎留言交流。

Spring-Security 自定义Filter完成验证码校验的更多相关文章

  1. 解决Spring Security自定义filter重复执行问题

    今天做项目的时候,发现每次拦截器日志都会打两遍,很纳闷,怀疑是Filter被执行了两遍.结果debug之后发现还真是!记录一下这个神奇的BUG! 问题描述 项目中使用的是Spring-security ...

  2. Spring Security 自定义 登陆 权限验证

    转载于:https://www.jianshu.com/p/6b8fb59b614b 项目简介 基于Spring Cloud 的项目,Spring Cloud是在Spring Boot上搭建的所以按照 ...

  3. Spring MVC 项目搭建 -6- spring security 使用自定义Filter实现验证扩展资源验证,使用数据库进行配置

    Spring MVC 项目搭建 -6- spring security使用自定义Filter实现验证扩展url验证,使用数据库进行配置 实现的主要流程 1.创建一个Filter 继承 Abstract ...

  4. Spring Security 自定义登录认证(二)

    一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...

  5. spring security自定义指南

    序 本文主要研究一下几种自定义spring security的方式 主要方式 自定义UserDetailsService 自定义passwordEncoder 自定义filter 自定义Authent ...

  6. (二)spring Security 自定义登录页面与校验用户

    文章目录 配置 security 配置下 MVC 自定义登录页面 自定义一个登陆成功欢迎页面 效果图 小结: 使用 Spring Boot 的快速创建项目功能,勾选上本篇博客需要的功能:web,sec ...

  7. Spring Security 自定义登录页面

    SpringMVC + Spring Security,自定义登录页面登录验证 学习参考:http://www.mkyong.com/spring-security/spring-security-f ...

  8. 【JavaEE】SSH+Spring Security自定义Security的部分处理策略

    本文建立在 SSH与Spring Security整合 一文的基础上,从这篇文章的example上做修改,或者从 配置了AOP 的example上做修改皆可.这里主要补充我在实际使用Spring Se ...

  9. spring security 4 filter 顺序及作用

    Spring Security 有两个作用:认证和授权 一.Srping security 4 filter 别名及顺序 spring security 4 标准filter别名和顺序,因为经常要用就 ...

随机推荐

  1. [知了堂学习笔记]_MVC设计模式与JavaWEB三层架构

    一.MVC设计模式 MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controlle ...

  2. 使用 cURL 度量 Web 站点的响应时间

    curl -o /dev/null -s -w %{time_connect}:%{time_starttransfer}:%{time_total} http://www.canada.com 0. ...

  3. 2017-07-04(sudo wc sort)

    sudo 作用 root把本来只能超级用户执行的命令,赋予普通用户执行. 添加 运行visudo命令,在文件底部添加信息即可! sudo -l  查看用户可以运行的命令 use1  ALL=(ALL) ...

  4. Java高级工程师——面试总结

    面试技巧 1.背熟你的简历 原因:面试的第一个问题,一般都是让你简单介绍下你自己,或者介绍一下你最近的项目,而一个面试者,如果连自己的简历都无法熟知,对里面提到的项目.技术都无法描述清楚的话,我想没有 ...

  5. underscore.js 源码阅读 一 整体结构

    // 整个underscore的实现包在一个立即执行函数中,避免污染全局对象 // 通过call(this)来入全局变量 (function() { // 缓存this var root = this ...

  6. 从LINQ开始之LINQ to Objects(上)

    LINQ概述 LINQ,语言集成查询(Language Integrated Query),它允许使用C#或VB代码以查询数据库相同的方式来操作不同的数据源. LINQ体系结构 从上图可以看出,LIN ...

  7. VisionPro学习笔记:用IEEE1394相机抓取图像

    1)找到采集卡: CogFrameGrabber1394DCAMs cameras = new CogFrameGrabber1394DCAMs(); 2)列举相连接的相机: ICogFrameGra ...

  8. Angular之ngRoute与uiRoute

    ngRoute不支持嵌套路由 用法如下: <!DOCTYPE html> <html lang="en" ng-app="myApp"> ...

  9. 前端之基础css

    一.anchor伪类,用于阅读文章. a:link(没有接触过的链接),用于链接常规状态 (末访问的链接)a:hover(鼠标放在链接上的状态) 用于产生视觉效果(已访问的链接)a:visited(访 ...

  10. C#:导入Excel通用类(CSV格式)

    一.引用插件LumenWorks.Framework.IO.dll(CsvReader) 插件下载地址:https://pan.baidu.com/s/1c3kTKli  提取密码 dz7j 二.定义 ...