⒈封装验证码类

 package cn.coreqi.security.validate;

 import java.awt.image.BufferedImage;
import java.time.LocalDateTime; public class ImageCode {
private BufferedImage image;
private String code;
private LocalDateTime expireTime; //过期时间 public ImageCode(BufferedImage image, String code, Integer expireIn) {
this.image = image;
this.code = code;
this.expireTime = LocalDateTime.now().plusSeconds(expireIn);
} public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) {
this.image = image;
this.code = code;
this.expireTime = expireTime;
} public boolean isExpried(){
return LocalDateTime.now().isAfter(expireTime);
} public BufferedImage getImage() {
return image;
} public void setImage(BufferedImage image) {
this.image = image;
} public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public LocalDateTime getExpireTime() {
return expireTime;
} public void setExpireTime(LocalDateTime expireTime) {
this.expireTime = expireTime;
}
}

⒉封装验证码控制器

 package cn.coreqi.security.controller;

 import cn.coreqi.security.validate.ImageCode;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest; import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random; @RestController
public class ValidateController { public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";
private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); @GetMapping("code/image")
public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
ImageCode imageCode = createImageCode(request);
sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,imageCode); response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
//response.setDateHeader("Expires", 0); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
encoder.encode(imageCode.getImage()); //ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream()); //当tomcat下temp文件夹不存在则"Can't create output stream"
} private ImageCode createImageCode(HttpServletRequest request) {
int width = 67;
int height = 23;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Random random = new Random(); g.setColor(getRandColor(200,250));
g.fillRect(0,0,width,height);
g.setFont(new Font("Times New Roman",Font.ITALIC,20));
g.setColor(getRandColor(160,200));
for (int i = 0;i < 155; i++){
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x,y,x+xl,y+yl);
}
String sRand = "";
for(int i = 0;i < 4; i++){
String rand = String.valueOf(random.nextInt(10));
sRand += rand;
g.setColor(new Color(20 + random.nextInt(110),20 + random.nextInt(110),20 + random.nextInt(110)));
g.drawString(rand,13 * i + 6,16);
}
g.dispose();
return new ImageCode(image,sRand,60);
} /**
* 生成随机背景条纹
* @param fc
* @param bc
* @return
*/
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if(fc > 255){
fc = 255;
}
if(bc > 255){
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r,g,b);
}
}

⒊放行验证码的Rest地址

⒋表单添加验证码

             <tr>
<td>图形验证码:</td>
<td>
<input type="text" name="imageCode">
<img src="/code/image">
</td>
</tr>

⒌声明一个验证码异常,用于抛出特定的验证码异常

 package cn.coreqi.security.validate;

 import org.springframework.security.core.AuthenticationException;

 public class ValidateCodeException extends AuthenticationException {
public ValidateCodeException(String msg) {
super(msg);
}
}

⒍创建一个过滤器,用于验证请求中的验证码是否正确

 package cn.coreqi.security.Filter;

 import cn.coreqi.security.validate.ImageCode;
import cn.coreqi.security.validate.ValidateCodeException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;
import cn.coreqi.security.controller.*; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; public class ValidateCodeFilter extends OncePerRequestFilter { private AuthenticationFailureHandler authenticationFailureHandler; private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return authenticationFailureHandler;
} public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
this.authenticationFailureHandler = authenticationFailureHandler;
} public SessionStrategy getSessionStrategy() {
return sessionStrategy;
} public void setSessionStrategy(SessionStrategy sessionStrategy) {
this.sessionStrategy = sessionStrategy;
} @Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
if (httpServletRequest.equals("/authentication/form") && httpServletRequest.getMethod().equals("post")) {
try {
validate(new ServletWebRequest(httpServletRequest)); }catch (ValidateCodeException e){
authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
return;
}
}
filterChain.doFilter(httpServletRequest,httpServletResponse); //如果不是登录请求,直接调用后面的过滤器链
} private void validate(ServletWebRequest request) throws ServletRequestBindingException {
ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(request,ValidateController.SESSION_KEY);
String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(),"imageCode");
if(!StringUtils.hasText(codeInRequest)){
throw new ValidateCodeException("验证码的值不能为空!");
}
if(codeInSession == null){
throw new ValidateCodeException("验证码不存在!");
}
if(codeInSession.isExpried()){
sessionStrategy.removeAttribute(request,ValidateController.SESSION_KEY);
throw new ValidateCodeException("验证码已过期!");
}
if(!codeInSession.getCode().equals(codeInRequest)){
throw new ValidateCodeException("验证码不正确!");
}
sessionStrategy.removeAttribute(request,ValidateController.SESSION_KEY);
}
}

⒎在SpringSecurity过滤器链中注册我们的过滤器

 package cn.coreqi.security.config;

 import cn.coreqi.security.Filter.ValidateCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private AuthenticationSuccessHandler coreqiAuthenticationSuccessHandler; @Autowired
private AuthenticationFailureHandler coreqiAuthenticationFailureHandler; @Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
} @Override
protected void configure(HttpSecurity http) throws Exception {
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(coreqiAuthenticationFailureHandler); //http.httpBasic() //httpBasic登录 BasicAuthenticationFilter
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) //加载用户名密码过滤器的前面
.formLogin() //表单登录 UsernamePasswordAuthenticationFilter
.loginPage("/coreqi-signIn.html") //指定登录页面
//.loginPage("/authentication/require")
.loginProcessingUrl("/authentication/form") //指定表单提交的地址用于替换UsernamePasswordAuthenticationFilter默认的提交地址
.successHandler(coreqiAuthenticationSuccessHandler) //登录成功以后要用我们自定义的登录成功处理器,不用Spring默认的。
.failureHandler(coreqiAuthenticationFailureHandler) //自己体会把
.and()
.authorizeRequests() //对授权请求进行配置
.antMatchers("/coreqi-signIn.html","/code/image").permitAll() //指定登录页面不需要身份认证
.anyRequest().authenticated() //任何请求都需要身份认证
.and().csrf().disable(); //禁用CSRF
//FilterSecurityInterceptor 整个SpringSecurity过滤器链的最后一环
}
}

SpringSecurity实现图形验证码功能的更多相关文章

  1. SpringSceurity(3)---图形验证码功能实现

    SpringSceurity(3)---图形验证码功能实现 有关springSceurity之前有写过两篇文章: 1.SpringSecurity(1)---认证+授权代码实现 2.SpringSec ...

  2. Tornado框架实现图形验证码功能

    图形验证码是项目开发过程中经常遇到的一个功能,在很多语言中都有对应的不同形式的图形验证码功能的封装,python 中同样也有类似的封装操作,通过绘制生成一个指定的图形数据,让前端HTML页面通过链接获 ...

  3. spring boot:spring security给用户登录增加自动登录及图形验证码功能(spring boot 2.3.1)

    一,图形验证码的用途? 1,什么是图形验证码? 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers ...

  4. 一百一十五:CMS系统之实现点击更换图形验证码功能

    把验证码渲染到到页面上 访问,显然,是标签有个内边距 去掉内边距 加一个class 如果放大看的话,还有问题 用js实现点击更换图形验证码:生成查询字符串的形式访问图形验证码接口的url,放到img标 ...

  5. SpringSceurity(4)---短信验证码功能实现

    SpringSceurity(4)---短信验证码功能实现 有关SpringSceurity系列之前有写文章 1.SpringSecurity(1)---认证+授权代码实现 2.SpringSecur ...

  6. Django学习笔记(17)——BBS+Blog项目开发(1)验证码功能的实现

    本文主要学习验证码功能的实现,为了项目BBS+Blog项目打下基础. 为了防止机器人频繁登陆网站或者破坏分子恶意登陆,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是“Com ...

  7. .Net Core 之 图形验证码 本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能。

    本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能. 通过测试的系统: Windows 8.1 64bit Ubuntu Server 16.04 LTS 64 ...

  8. 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...

  9. Java 前端加密传输后端解密以及验证码功能

    目录(?)[-] 加密解密 1 前端js加密概述 2 前后端加密解密 21 引用的js加密库 22 js加密解密 23 Java端加密解密PKCS5Padding与js的Pkcs7一致 验证码 1 概 ...

随机推荐

  1. flume常见异常汇总以及解决方案

    flume常见异常汇总以及解决方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际生产环境中,我用flume将kafka的数据定期的往hdfs集群中上传数据,也遇到过一系列的坑 ...

  2. sql递归查询 根据Id查所有子结点

    Declare @Id Int Set @Id = 0; ---在此修改父节点 With RootNodeCTE(D_ID,D_FatherID,D_Name,lv) As ( Select D_ID ...

  3. js静态方法与实例方法定义,js回调方法定义

    主要为了回调方法,随便把静态言法和实例方法也回顾一下. <script type="text/javascript"> var fun = { //下面是静态方法(第一 ...

  4. Ubuntu修改Apache默认Web端口

    改成你要的端口,默认为80,这里我改成了8080,https改成了444,保存之后寻找000/default.conf并修改成和ports.conf文件一样的http端口,然后重启Apache服务器即 ...

  5. jQuery中获取a标签的值

    如题,一组相同action的a标签,不同的是a标签的内容为搜索内容.点击页面显示不同的数据 刚开始试过在 a标签中添加 value值 和id 的值,结果在jQuery中获取值均失败! 后来发现,根本不 ...

  6. Understanding Favicon

    Favicon 简介 Favicon : 是favorites icon 的缩写,被称为website icon . page icon. urlicon. 最初定义一个favicon的方法是将一个名 ...

  7. java 的三种代理

    java的三种代理模式   1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作, ...

  8. 解决IOS移动端固定定位失效问题

    根据浏览器窗口position:fixed; 定位在底部的元素,会随着屏幕的滚动而滚动,在iOS系统上不起作用. <div class="header">头部</ ...

  9. MySQL 数据库应用程序编程

    普通用户使用客户端应用程序(Client Application)和服务器程序(Server Application)通信以取得服务, 而服务器程序通常要和数据库服务器通信以取得数据存取服务, 这时就 ...

  10. office 2016 破解教程

    骤: 下载安装包——>安装(断网状态)——>下载破解工具——>破解完成 1. 下载 office2016,大家进入下面的链接进行 http://pan.baidu.com/s/1mi ...