代码地址如下:
http://www.demodashi.com/demo/14280.html

项目介绍

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
Spring Security的核心功能就是对用户进行身份认证和授权。而他的认证机制就是通过Spring Security一系列的过滤器链,当一个请求来的时候,首先要通过过滤器链的校验,校验通过之后才会访问用户各种信息

但是在进行一些登录,注册等操作的时候,往往还需要使用验证码来进行校验。本案例采用的面向接口编程,将自定义的验证码过滤器添加到Spring Security的过滤器链上来实现灵活的,可扩展,可重用,可配置的验证码验证。

项目结构

项目实现过程

1. 首先,定义图片验证码实体类。用来封装验证码相关信息
public class ImageCode{

    private BufferedImage image;
//失效时间
private LocalDateTime expireTime;
//验证码
private String code; public ImageCode(BufferedImage image, String code, int expireIn){
this.code = code;
this.expireTime = LocalDateTime.now().plusSeconds(expireIn);
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;
} public BufferedImage getImage() {
return image;
} public void setImage(BufferedImage image) {
this.image = image;
} public boolean isExpried() {
return LocalDateTime.now().isAfter(expireTime);
}
}
2.验证码属性配置。
  • 系统配置
 @ConfigurationProperties(prefix = "jcohy.security")
public class SecurityProperties { /**
* 验证码配置
*/
private ValidateCodeProperties validateCode = new ValidateCodeProperties(); public ValidateCodeProperties getValidateCode() {
return validateCode;
} public void setValidateCode(ValidateCodeProperties validateCode) {
this.validateCode = validateCode;
}
}
  • 验证码配置。方便大家进行扩展。如要添加其他验证配置,添加其他配置属性类即可
public class ValidateCodeProperties {
/**
* 图片验证码选项
*/
private ImageCodeProperties imageCode = new ImageCodeProperties(); public ImageCodeProperties getImageCode() {
return imageCode;
} public void setImageCode(ImageCodeProperties imageCode) {
this.imageCode = imageCode;
}
}
  • 图片验证码配置
public class ImageCodeProperties{

    private int length = 4;

    private int expireIn = 60;
/**
* 验证码的宽
*/
private int width = 67; /**
* 验证码的高
*/
private int height = 23; public int getLength() {
return length;
} public void setLength(int length) {
this.length = length;
} public int getExpireIn() {
return expireIn;
} public void setExpireIn(int expireIn) {
this.expireIn = expireIn;
} public int getWidth() {
return width;
} public void setWidth(int width) {
this.width = width;
} public int getHeight() {
return height;
} public void setHeight(int height) {
this.height = height;
}
}
  • 使配置生效
 @Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class PropertiesConfig { }
3.关于验证码配置的说明
  • 验证码的配置分为三个级别,
  • 默认配置:当什么都不配置时,采用默认配置
  • 应用级配置:配置在application.properties文件中。例如:jcohy.security.validateCode.imageCode.width=100
  • 请求级配置:在请求中携带验证码相关参数。例如:"/code/image?width=100"。说明指定验证码图片宽度为100px。

其优先级如下:请求级配置>应用级配置>默认配置。当前一个存在时,会覆盖后面的配置。

4.好了,前面已经对验证码的基本属性和配置已经编写完成,接下来根据配置文件属性生成验证码图片。此处采用的是面向接口编程的方法,方便大家定制不同的验证码生成策略,多种方式验证。使用更高级的验证码策略等。我这里只提供了一种简单的实现。
public interface ValidateCodeGenerator {
/**
* 图形验证码实现方法接口
* @param request
* @return
*/
ImageCode generate(ServletWebRequest request);
}
public class ImageCodeGenerator implements ValidateCodeGenerator{

    /**
* 系统配置
*/
@Autowired
private SecurityProperties securityProperties; @Override
public ImageCode generate(ServletWebRequest request) {
....
....
//绘制并生成图片验证码过程
....
....
} public SecurityProperties getSecurityProperties() {
return securityProperties;
} public void setSecurityProperties(SecurityProperties securityProperties) {
this.securityProperties = securityProperties;
}
}
5.图片验证码生成的过程已经完成,接下来就是对验证码进行验证了。我们使用过滤器来进行验证
@Component("validateCodeFilter")
public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean { /**
* 验证码校验失败处理器
*/
private AuthenticationFailureHandler authenticationFailureHandler; private SecurityProperties securityProperties; private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
//需要进行验证的的请求地址。
private Set<String> urls = new HashSet<>(); /**
* 验证请求url与配置的url是否匹配的工具类
*/
private AntPathMatcher pathMatcher = new AntPathMatcher(); @Override
public void afterPropertiesSet() throws ServletException {
super.afterPropertiesSet();
//“/authentication/form”为登录请求。
urls.add("/authentication/form");
} @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
boolean action = false;
for(String url:urls){
if(pathMatcher.match(url,request.getRequestURI())){
action = true;
}
} if(action){
try{
validate(new ServletWebRequest(request));
}catch (ValidateCodeException e){
authenticationFailureHandler.onAuthenticationFailure(request,response,e);
return;
}
}
chain.doFilter(request, response); } private void validate(ServletWebRequest request) throws ServletRequestBindingException {
ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(request, UserController.SESSION_KEY);
String codeInRequest;
try {
codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(),
"imageCode");
} catch (ServletRequestBindingException e) {
throw new ValidateCodeException("获取验证码的值失败");
} if (StringUtils.isBlank(codeInRequest)) {
throw new ValidateCodeException("imageCode:验证码的值不能为空");
} if (codeInSession == null) {
throw new ValidateCodeException("imageCode:验证码不存在");
} if (codeInSession.isExpried()) {
sessionStrategy.removeAttribute(request,UserController.SESSION_KEY);
throw new ValidateCodeException("imageCode: 验证码已过期");
} if (!StringUtils.equals(codeInSession.getCode(), codeInRequest)) {
throw new ValidateCodeException("imageCode:验证码不匹配");
}
sessionStrategy.removeAttribute(request,UserController.SESSION_KEY);
} public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return authenticationFailureHandler;
} public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
this.authenticationFailureHandler = authenticationFailureHandler;
} public SecurityProperties getSecurityProperties() {
return securityProperties;
} public void setSecurityProperties(SecurityProperties securityProperties) {
this.securityProperties = securityProperties;
}
}
  • 将生成验证码的Bean加入到容器中
@Configuration
public class ValidateCodeBeanConfig { @Autowired
private SecurityProperties securityProperties;
//条件匹配。此处可扩展其他的验证条件和相应生成器
@Bean
@ConditionalOnMissingBean(name = "imageCodeGenerator")
public ValidateCodeGenerator imageCodeGenerator(){
ImageCodeGenerator imageCodeGenerator = new ImageCodeGenerator();
imageCodeGenerator.setSecurityProperties(securityProperties);
return imageCodeGenerator;
}
}
6。将过滤器添加到过滤器链上
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 验证码校验失败处理器
*/
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler; @Autowired
private AuthenticationSuccessHandler JcohyAuthenticationSuccessHandler;
/**
* 系统配置信息
*/
@Autowired
private SecurityProperties securityProperties; @Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity http) throws Exception {
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet();
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
.formLogin()
.loginPage("/signIn.html")
.loginProcessingUrl("/authentication/form")
.successHandler(JcohyAuthenticationSuccessHandler)
.and()
.authorizeRequests()
.antMatchers("/signIn.html"
,"/code/image").permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable();
}
}

项目运行

  • 本项目使用IntelliJ IDEA工具。使用maven构建。下载后导入到工具中可直接运行
  • 运行成功后访问http://localhost:8080,出现如下界面

  • 本项目主要侧重于验证码的生成和验证,用户部分比较简单,用户名随便写,密码是123456,想要修改密码可以在MyUserDetailService类中修改。

    SpringBoot之自定义验证码

代码地址如下:
http://www.demodashi.com/demo/14280.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

SpringBoot之自定义验证码的更多相关文章

  1. Springboot 之 自定义配置文件及读取配置文件

    本文章来自[知识林] 读取核心配置文件 核心配置文件是指在resources根目录下的application.properties或application.yml配置文件,读取这两个配置文件的方法有两 ...

  2. Springboot 之 自定义配置文件及读取配置文件注意:配置文件中的字符串不要有下划线 .配置中 key不能带下划线,value可以(下划线的坑,坑了我两天..特此纪念)

    注意:配置文件中的字符串不要有下划线 .配置中  key不能带下划线,value可以 错误的.不能读取的例子: mySet .ABAP_AS_POOLED      =  ABAP_AS_WITH_P ...

  3. springboot扫描自定义的servlet和filter代码详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 这几天使用spring boot编写公司一个应用,在编写了一个filter,用于指定编码的filter,如下: /** ...

  4. SpringBoot Jpa 自定义查询

    SpringBoot Jpa 自定义查询 持久层Domain public interface BaomingDao extends JpaRepository<BaomingBean,Inte ...

  5. 详解Springboot中自定义SpringMVC配置

    详解Springboot中自定义SpringMVC配置 WebMvcConfigurer接口 ​ 这个接口可以自定义拦截器,例如跨域设置.类型转化器等等.可以说此接口为开发者提前想到了很多拦截层面的需 ...

  6. SpringBoot系列——自定义统一异常处理

    前言 springboot内置的/error错误页面并不一定适用我们的项目,这时候就需要进行自定义统一异常处理,本文记录springboot进行自定义统一异常处理. 1.使用@ControllerAd ...

  7. js自定义验证码

    分享一个js自定义的验证码 window.onload = function () {     var code;     $('.changePassword').click(function () ...

  8. SpringBoot编写自定义的starter 专题

    What’s in a name All official starters follow a similar naming pattern; spring-boot-starter-*, where ...

  9. springboot读取自定义配置文件节点

    今天和大家分享的是自定义配置信息的读取:近期有写博客这样的计划,分别交叉来写springboot方面和springcloud方面的文章,因为springboot预计的篇章很多,这样cloud的文章就需 ...

随机推荐

  1. Unity3d操作的一些技巧知识点和BUG解决方案

    自己记录一些东西,转载请良心注明出处.     1.如何同时打开两个UNITY3D项目. 有时候需要对比,或者需要添加另一个项目的某资源到目前项目,同时打开两个项目看起来会比较明了.如果直接打开的话, ...

  2. 使用msm配置分布式tomat,实现session共享

    一,环境说明 操作系统是Windows7家庭版(有点不专业哦,呵呵!),JDK是1.6的版本, Tomcat是apache-tomcat-6.0.35-windows-x86,下载链接:http:// ...

  3. jquery、js获取table,遍历输出tr中各个td的内容。

    首先,依赖jquery.. $('#btntb').click(function(){ $('#tab tr').each(function(i){ // 遍历 tr $(this).children ...

  4. 快速近似最近邻搜索库 FLANN - Fast Library for Approximate Nearest Neighbors

    What is FLANN? FLANN is a library for performing fast approximate nearest neighbor searches in high ...

  5. 【HDOJ】【1964】Pipes

    插头DP 做完Formula 1以后这就是傻逼题了……直接将“数路径方案数”改为“计算路径长度取最小值”即可,没多大难度 都不用判当前格子是否能够到达的……不过!外边的一圈“墙”还是要加的!不然会有冗 ...

  6. 怎样通过terminal得到AWS EC2 instance的ip

    可得到private ip,也是本地的ip.事实上通过ifconfig也能得到: GET http://169.254.169.254/latest/meta-data/local-ipv4 公共ip ...

  7. 混沌数学之离散点集图形DEMO

    最近看了很多与混沌相关的知识,并写了若干小软件.混沌现象是个有意思的东西,同时混沌也能够生成许多有意思的图形.混沌学的现代研究使人们渐渐明白,十分简单的数学方程完全可以模拟系统如瀑布一样剧烈的行为.输 ...

  8. PreparedStatement 使用like 模糊查询

    PreparedStatement 使用like 在使用PreparedStatement进行模糊查询的时候废了一番周折,以前一直都没有注意这个问题. 一般情况下我们进行精确查询,sql语句类似:se ...

  9. [转贴]SSL工作原理

    SSL协议使用不对称加密技术实现会话双方之间信息的安全传递.可以实现信息传递的保密性.完整性,并且会话双方能鉴别对方身份.不同于常用的http协议,我们在与网站建立SSL安全连接时使用https协议, ...

  10. 解决报错"Your security system have blocked an application with expired or not yet valid certificate from running"

    方法如下: Go to Control Panel Java in the Security tab click the "Edit Site List-" button clic ...