博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringSecurity实现图形验证码功能
阅读量:5167 次
发布时间:2019-06-13

本文共 11347 字,大约阅读时间需要 37 分钟。

⒈封装验证码类

1 package cn.coreqi.security.validate; 2  3 import java.awt.image.BufferedImage; 4 import java.time.LocalDateTime; 5  6 public class ImageCode { 7     private BufferedImage image; 8     private String code; 9     private LocalDateTime expireTime;   //过期时间10 11     public ImageCode(BufferedImage image, String code, Integer expireIn) {12         this.image = image;13         this.code = code;14         this.expireTime = LocalDateTime.now().plusSeconds(expireIn);15     }16 17     public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) {18         this.image = image;19         this.code = code;20         this.expireTime = expireTime;21     }22 23     public boolean isExpried(){24         return LocalDateTime.now().isAfter(expireTime);25     }26 27     public BufferedImage getImage() {28         return image;29     }30 31     public void setImage(BufferedImage image) {32         this.image = image;33     }34 35     public String getCode() {36         return code;37     }38 39     public void setCode(String code) {40         this.code = code;41     }42 43     public LocalDateTime getExpireTime() {44         return expireTime;45     }46 47     public void setExpireTime(LocalDateTime expireTime) {48         this.expireTime = expireTime;49     }50 }

⒉封装验证码控制器

1 package cn.coreqi.security.controller; 2  3 import cn.coreqi.security.validate.ImageCode; 4 import com.sun.image.codec.jpeg.JPEGCodec; 5 import com.sun.image.codec.jpeg.JPEGImageEncoder; 6 import org.springframework.social.connect.web.HttpSessionSessionStrategy; 7 import org.springframework.social.connect.web.SessionStrategy; 8 import org.springframework.web.bind.annotation.GetMapping; 9 import org.springframework.web.bind.annotation.RestController;10 import org.springframework.web.context.request.ServletWebRequest;11 12 import javax.imageio.ImageIO;13 import javax.servlet.http.HttpServletRequest;14 import javax.servlet.http.HttpServletResponse;15 import java.awt.*;16 import java.awt.image.BufferedImage;17 import java.io.IOException;18 import java.util.Random;19 20 @RestController21 public class ValidateController {22 23     public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";24     private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();25 26     @GetMapping("code/image")27     public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {28         ImageCode imageCode = createImageCode(request);29         sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,imageCode);30         31         response.setHeader("Pragma","No-cache");32         response.setHeader("Cache-Control","no-cache");33         //response.setDateHeader("Expires", 0);34         35         JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());36         encoder.encode(imageCode.getImage());37         38         //ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream());    //当tomcat下temp文件夹不存在则"Can't create output stream"39     }40 41     private ImageCode createImageCode(HttpServletRequest request) {42         int width = 67;43         int height = 23;44         BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);45 46         Graphics g = image.getGraphics();47 48         Random random = new Random();49 50         g.setColor(getRandColor(200,250));51         g.fillRect(0,0,width,height);52         g.setFont(new Font("Times New Roman",Font.ITALIC,20));53         g.setColor(getRandColor(160,200));54         for (int i = 0;i < 155; i++){55             int x = random.nextInt(width);56             int y = random.nextInt(height);57             int xl = random.nextInt(12);58             int yl = random.nextInt(12);59             g.drawLine(x,y,x+xl,y+yl);60         }61         String sRand = "";62         for(int i = 0;i < 4; i++){63             String rand = String.valueOf(random.nextInt(10));64             sRand += rand;65             g.setColor(new Color(20 + random.nextInt(110),20 + random.nextInt(110),20 + random.nextInt(110)));66             g.drawString(rand,13 * i + 6,16);67         }68         g.dispose();69         return new ImageCode(image,sRand,60);70     }71 72     /**73      * 生成随机背景条纹74      * @param fc75      * @param bc76      * @return77      */78     private Color getRandColor(int fc, int bc) {79         Random random = new Random();80         if(fc > 255){81             fc = 255;82         }83         if(bc > 255){84             bc = 255;85         }86         int r = fc + random.nextInt(bc - fc);87         int g = fc + random.nextInt(bc - fc);88         int b = fc + random.nextInt(bc - fc);89         return new Color(r,g,b);90     }91 }

 

⒊放行验证码的Rest地址

⒋表单添加验证码

1             2                 图形验证码:3                 4                     5                     6                 7             

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

1 package cn.coreqi.security.validate;2 3 import org.springframework.security.core.AuthenticationException;4 5 public class ValidateCodeException extends AuthenticationException {6     public ValidateCodeException(String msg) {7         super(msg);8     }9 }

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

1 package cn.coreqi.security.Filter; 2  3 import cn.coreqi.security.validate.ImageCode; 4 import cn.coreqi.security.validate.ValidateCodeException; 5 import org.springframework.security.web.authentication.AuthenticationFailureHandler; 6 import org.springframework.social.connect.web.HttpSessionSessionStrategy; 7 import org.springframework.social.connect.web.SessionStrategy; 8 import org.springframework.util.StringUtils; 9 import org.springframework.web.bind.ServletRequestBindingException;10 import org.springframework.web.bind.ServletRequestUtils;11 import org.springframework.web.context.request.ServletWebRequest;12 import org.springframework.web.filter.OncePerRequestFilter;13 import cn.coreqi.security.controller.*;14 15 import javax.servlet.FilterChain;16 import javax.servlet.ServletException;17 import javax.servlet.http.HttpServletRequest;18 import javax.servlet.http.HttpServletResponse;19 import java.io.IOException;20 21 public class ValidateCodeFilter extends OncePerRequestFilter {22 23     private AuthenticationFailureHandler authenticationFailureHandler;24 25     private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();26 27     public AuthenticationFailureHandler getAuthenticationFailureHandler() {28         return authenticationFailureHandler;29     }30 31     public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {32         this.authenticationFailureHandler = authenticationFailureHandler;33     }34 35     public SessionStrategy getSessionStrategy() {36         return sessionStrategy;37     }38 39     public void setSessionStrategy(SessionStrategy sessionStrategy) {40         this.sessionStrategy = sessionStrategy;41     }42 43     @Override44     protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {45         if (httpServletRequest.equals("/authentication/form") && httpServletRequest.getMethod().equals("post")) {46             try {47                 validate(new ServletWebRequest(httpServletRequest));48 49             }catch (ValidateCodeException e){50                 authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);51                 return;52             }53         }54         filterChain.doFilter(httpServletRequest,httpServletResponse);   //如果不是登录请求,直接调用后面的过滤器链55     }56 57     private void validate(ServletWebRequest request) throws ServletRequestBindingException {58         ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(request,ValidateController.SESSION_KEY);59         String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(),"imageCode");60         if(!StringUtils.hasText(codeInRequest)){61             throw new ValidateCodeException("验证码的值不能为空!");62         }63         if(codeInSession == null){64             throw new ValidateCodeException("验证码不存在!");65         }66         if(codeInSession.isExpried()){67             sessionStrategy.removeAttribute(request,ValidateController.SESSION_KEY);68             throw new ValidateCodeException("验证码已过期!");69         }70         if(!codeInSession.getCode().equals(codeInRequest)){71             throw new ValidateCodeException("验证码不正确!");72         }73         sessionStrategy.removeAttribute(request,ValidateController.SESSION_KEY);74     }75 }

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

1 package cn.coreqi.security.config; 2  3 import cn.coreqi.security.Filter.ValidateCodeFilter; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Configuration; 7 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 import org.springframework.security.crypto.password.NoOpPasswordEncoder;10 import org.springframework.security.crypto.password.PasswordEncoder;11 import org.springframework.security.web.authentication.AuthenticationFailureHandler;12 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;13 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;14 15 @Configuration16 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {17 18     @Autowired19     private AuthenticationSuccessHandler coreqiAuthenticationSuccessHandler;20 21     @Autowired22     private AuthenticationFailureHandler coreqiAuthenticationFailureHandler;23 24     @Bean25     public PasswordEncoder passwordEncoder(){26         return NoOpPasswordEncoder.getInstance();27     }28 29     @Override30     protected void configure(HttpSecurity http) throws Exception {31         ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();32         validateCodeFilter.setAuthenticationFailureHandler(coreqiAuthenticationFailureHandler);33 34         //http.httpBasic()    //httpBasic登录 BasicAuthenticationFilter35         http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)    //加载用户名密码过滤器的前面36                 .formLogin()    //表单登录 UsernamePasswordAuthenticationFilter37                 .loginPage("/coreqi-signIn.html")  //指定登录页面38                 //.loginPage("/authentication/require")39                 .loginProcessingUrl("/authentication/form") //指定表单提交的地址用于替换UsernamePasswordAuthenticationFilter默认的提交地址40                 .successHandler(coreqiAuthenticationSuccessHandler) //登录成功以后要用我们自定义的登录成功处理器,不用Spring默认的。41                 .failureHandler(coreqiAuthenticationFailureHandler) //自己体会把42                 .and()43                 .authorizeRequests()    //对授权请求进行配置44                 .antMatchers("/coreqi-signIn.html","/code/image").permitAll() //指定登录页面不需要身份认证45                 .anyRequest().authenticated()  //任何请求都需要身份认证46                 .and().csrf().disable();    //禁用CSRF47             //FilterSecurityInterceptor 整个SpringSecurity过滤器链的最后一环48     }49 }

 

转载于:https://www.cnblogs.com/fanqisoft/p/10630556.html

你可能感兴趣的文章
CES1
查看>>
CES2
查看>>
文件方式实现完整的英文词频统计实例
查看>>
ListControl的用法
查看>>
单个SWF文件loading加载详解(转)
查看>>
SQLServer中的CTE通用表表达式
查看>>
linux第1天 fork exec 守护进程
查看>>
Ajax原理学习
查看>>
最新最潮的24段魔尺立体几何玩法(2016版)
查看>>
C# 3.0 LINQ的准备工作
查看>>
CodeForces - 449D Jzzhu and Numbers
查看>>
mysql批量插入更新操作
查看>>
静态代码审查工具FxCop插件开发(c#)
查看>>
创建代码仓库
查看>>
理解裸机部署过程ironic
查看>>
Django 组件-ModelForm
查看>>
zabbix 二 zabbix agent 客户端
查看>>
大数据分析中,有哪些常见的大数据分析模型?
查看>>
Generate SSH key
查看>>
URL中不应出现汉字
查看>>