⒈封装验证码类

 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. thinkphp 攻略

    php框架     一.真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难, ...

  2. Mysql的SQL语句常用基本命令

    SQL语句分类:DDL,DML,DQL,DCL. 1.数据库操作: 创建数据库:create database 数据库名 charater set gbk; 删除数据库:drop database 数 ...

  3. Prometheus-自定义Node_Exporter

    标量(Scalar):一个浮点型的数字值 标量只有一个数字,没有时序. 需要注意的是,当使用表达式count(http_requests_total),返回的数据类型,依然是瞬时向量.用户可以通过内置 ...

  4. netty的数据通信之心跳检测

    问题1:我们想实现客户端和服务端建立连接之后,5秒钟之后如果没有数据传输就关闭与客户端的连接. 解决办法:在服务端加上下面一条代码 ch.pipeline().addLast(new ReadTime ...

  5. sqlyog创建数据库表关系图

    作为一个后台前端,数据库,需求分析,运维,PPT全包的码农来说.uml建模不存在的,对不起我没有时间,就用sqlyog拉几个你看看吧.看的懂的一眼就看清了,看不懂的整再好也是白瞎. 第一步:选择增强工 ...

  6. spring-data-redis时效设置

    本人转自http://hbxflihua.iteye.com/blog/2320584#bc2396403 spring目前在@Cacheable和@CacheEvict等注解上不支持缓存时效设置,只 ...

  7. HDU 1033(坐标移动 模拟)

    题意是说有一点从(300,410)的位置出发,向右移动到(310,410)后开始转向,A 表示向顺时针转,V 表示向逆时针转,每次转向后沿当前方向前进 10 个单位, 输出其坐标,再补充一点格式上的东 ...

  8. Oracle的to_char()函数使用

    (1)用作日期转换: to_char(date,'格式'); select to_date('2005-01-01 ','yyyy-MM-dd') from dual; select to_char( ...

  9. ASP.NET Web API 2 之 HttpRequestMessage 对象

    Ø  前言 在 Web API 中经常会使用到 HttpRequestMessage 和 HttpResponseMessage 对象,这两个对象封装了对 Web API 的请求和响应,位于 Syst ...

  10. Tomcat下载,及环境变量配置

    首先,介绍一下Tomcat: Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公 ...