github:https://github.com/peterowang/shiro/

这里实现验证码校验的思路是自己添加一个Filter继承FormAuthenticationFilter,FormAuthenticationFilter负责表单验证,shiro会先在FormAuthenticationFilter子类去校验验证码,然后再去做身份验证。

生成验证码这里使用Google的Kaptcha框架。

1.添加依赖

<!--google的验证码框架-->
<dependency>
<groupId>com.google.code.kaptcha</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3</version>
</dependency>

2.拓展UsernamePasswordToken,将验证码包含进去:

在com.example.demo.config.Shiro包下添加以下类:

package com.example.demo.config.shiro;

import org.apache.shiro.authc.UsernamePasswordToken;

/**
* 对UsernamePasswordToken进行二次封装,将验证码加入
* Created by BFD-593 on 2017/8/10.
*/
public class CaptchaUsernamePasswordToken extends UsernamePasswordToken {
/*
* serialVersionUID用来作为Java对象序列化中的版本标示之用;
* 如果一个序列化类没有声明这样一个static final的常量,
* JVM会根据各种参数为这个类计算一个; 对于同样一个类,
* 不同版本的JDK可能会得出不同的serivalVersionUID;
* 所以为了兼容性,一般自己加一个,至于值自己定就行,不一定是1L。自己练习的时候加不加没什么区别。
*
* */
private static final long serivalVersionUID = 1L; //验证码字符串
private String captcha;
public CaptchaUsernamePasswordToken(String username, char[] password, boolean rememberMe, String host, String captcha) {
super(username,password,rememberMe, host);
this.captcha = captcha;
}
public static long getSerivalVersionUID() {
return serivalVersionUID;
} public String getCaptcha() {
return captcha;
} public void setCaptcha(String captcha) {
this.captcha = captcha;
} }
顺便再Exception包下添加一个验证码异常的类,方便在controller中捕获:
package com.example.demo.config.ExceptionResolver;

import org.apache.shiro.authc.AuthenticationException;

/**
* 将shiro异常进行二次封装,抛出该异常表示验证码不正确,好让controller通过判断进行error设置展示在前台
* Created by BFD-593 on 2017/8/10.
*/
public class IncorrectCaptchaException extends AuthenticationException {
/*
* serialVersionUID用来作为Java对象序列化中的版本标示之用;
* 如果一个序列化类没有声明这样一个static final的常量,
* JVM会根据各种参数为这个类计算一个; 对于同样一个类,
* 不同版本的JDK可能会得出不同的serivalVersionUID;
* 所以为了兼容性,一般自己加一个,至于值自己定就行,不一定是1L。自己练习的时候加不加没什么区别。
*
* */
private static final long serialVersionUID = 1L; public IncorrectCaptchaException() {
super();
}
public IncorrectCaptchaException(String message, Throwable cause) {
super(message, cause);
}
public IncorrectCaptchaException(String message) {
super(message);
} public IncorrectCaptchaException(Throwable cause) {
super(cause);
}
}

2.添加校验用的Filter

package com.example.demo.filter;

import com.example.demo.config.ExceptionResolver.IncorrectCaptchaException;
import com.example.demo.config.shiro.CaptchaUsernamePasswordToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; /**
* 对FormAuthenticationFilter进行封装
* 这里实现验证码校验的思路是自己添加一个Filter继承FormAuthenticationFilter,
* FormAuthenticationFilter负责表单验证,
* shiro会先在FormAuthenticationFilter子类去校验验证码,然后再去做身份验证。
* Created by BFD-593 on 2017/8/10.
*/
public class KaptchaFilter extends FormAuthenticationFilter{ public static final String DEFAULT_CAPTCHA_PARAM = "captcha";//此处的值应和前台验证码值的name对应 private String captchaParam = DEFAULT_CAPTCHA_PARAM; @Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { CaptchaUsernamePasswordToken token = createToken(request, response);
try {
doCaptchaValidate((HttpServletRequest) request, token);//先做校验验证码是否正确
Subject subject = getSubject(request, response);
subject.login(token);//身份验证
return onLoginSuccess(token, subject, request, response);//设置成功跳转
} catch (AuthenticationException e) {
return onLoginFailure(token,e,request,response);//设置保存异常对象
}
} //验证码校验
protected void doCaptchaValidate(HttpServletRequest request, CaptchaUsernamePasswordToken token) { // 从session中获取图形吗字符串,这个是由goggle的框架帮我们设置到session中的
String captcha = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); // 校验
if (captcha == null || !captcha.equals(token.getCaptcha())) {
throw new IncorrectCaptchaException();
}
}
/*
* 将username password host rememberMe 和captcha封装到我们自己的CaptchaUsernamePasswordToken中
* */
@Override
protected CaptchaUsernamePasswordToken createToken(ServletRequest request, ServletResponse response) { String username = getUsername(request);
String password = getPassword(request);
String host = getHost(request);
boolean rememberMe = isRememberMe(request);
String captcha = getCaptcha(request);
return new CaptchaUsernamePasswordToken(username,password.toCharArray(),rememberMe,host,captcha);
}
/*
* 在request请求中获取name=captcha的值(也就是验证码的值)
* */
protected String getCaptcha(ServletRequest request) {
return WebUtils.getCleanParam(request, getCaptchaParam());
} //保存异常对象到request
@Override
protected void setFailureAttribute(ServletRequest request, org.apache.shiro.authc.AuthenticationException ae) {
request.setAttribute(getFailureKeyAttribute(), ae);
} public String getCaptchaParam() {
return captchaParam;
} public void setCaptchaParam(String captchaParam) {
this.captchaParam = captchaParam;
} }
com.example.demo.config.Shiro.ShiroConfiguration的ShiroFilterFactoryBean中添加验证码filter。
.....
//将我们自己的拦截器注入到shiro中
Map<String, Filter> filterMap = shiroFilterFactoryBean.getFilters();//先获取shiro内部拦截器
KaptchaFilter kaptchaFilter = new KaptchaFilter();//初始化自己的拦截器
filterMap.put("kaptchaFilter", kaptchaFilter);//加入我们的拦截器
shiroFilterFactoryBean.setFilters(filterMap);//注入
....
filterChainDefinitionMap.put("/login", "kaptchaFilter");//设置登录时使用kaptchaFilter我们自己的拦截器
filterChainDefinitionMap.put("/kaptcha.jpg", "anon");//图片验证码(kaptcha框架,会访问localhost:8080/kaptcha.jpg来自动生成验证码)
....
接下来需要在启动类中注册KaptchaServlet.
    //配置kaptcha图片验证码框架提供给Servlet
@Bean
public ServletRegistrationBean kaptchaServlet() {
//图片验证码(kaptcha框架,会访问localhost:8080/kaptcha.jpg来自动生成验证码)
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new KaptchaServlet(), "/kaptcha.jpg");
//设置初始化参数,供kaptcha生成指定样式的验证码
registrationBean.addInitParameter(Constants.KAPTCHA_SESSION_CONFIG_KEY,
Constants.KAPTCHA_SESSION_KEY);
registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_HEIGHT,"60");//高度
registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_WIDTH,"150");
registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE,"50");//字体大小
registrationBean.addInitParameter(Constants.KAPTCHA_BORDER_THICKNESS,"1"); //边框
registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "red"); //文字颜色 //可以设置很多属性,具体看com.google.code.kaptcha.Constants
// kaptcha.border 是否有边框 默认为true 我们可以自己设置yes,no
// kaptcha.border.color 边框颜色 默认为Color.BLACK
// kaptcha.border.thickness 边框粗细度 默认为1
// kaptcha.producer.impl 验证码生成器 默认为DefaultKaptcha
// kaptcha.textproducer.impl 验证码文本生成器 默认为DefaultTextCreator
// kaptcha.textproducer.char.string 验证码文本字符内容范围 默认为abcde2345678gfynmnpwx
// kaptcha.textproducer.char.length 验证码文本字符长度 默认为5
// kaptcha.textproducer.font.names 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
// kaptcha.textproducer.font.size 验证码文本字符大小 默认为40
// kaptcha.textproducer.font.color 验证码文本字符颜色 默认为Color.BLACK
// kaptcha.textproducer.char.space 验证码文本字符间距 默认为2
// kaptcha.noise.impl 验证码噪点生成对象 默认为DefaultNoise
// kaptcha.noise.color 验证码噪点颜色 默认为Color.BLACK
// kaptcha.obscurificator.impl 验证码样式引擎 默认为WaterRipple
// kaptcha.word.impl 验证码文本字符渲染 默认为DefaultWordRenderer
// kaptcha.background.impl 验证码背景生成器 默认为DefaultBackground
// kaptcha.background.clear.from 验证码背景颜色渐进 默认为Color.LIGHT_GRAY
// kaptcha.background.clear.to 验证码背景颜色渐进 默认为Color.WHITE
// kaptcha.image.width 验证码图片宽度 默认为200
// kaptcha.image.height 验证码图片高度 默认为50
return registrationBean;
}

3.最后,在login.html页面把验证码添加进去:

<div><label> 验证码 : <input type="text" name="captcha" placeholder="验证码"/> </label></div>
<div><img th:src="@{/kaptcha.jpg}"></div>

好了,在进入login登录页面

springboot集成shiro实现验证码校验的更多相关文章

  1. SpringBoot整合Shiro完成验证码校验

    SpringBoot整合Shiro完成验证码校验 上一篇:SpringBoot整合Shiro使用Redis作为缓存 首先编写生成验证码的工具类 package club.qy.datao.utils; ...

  2. Apache Shiro:【2】与SpringBoot集成完成登录验证

    Apache Shiro:[2]与SpringBoot集成完成登录验证 官方Shiro文档:http://shiro.apache.org/documentation.html Shiro自定义Rea ...

  3. springboot集成shiro实现权限认证

    github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...

  4. SpringBoot集成Shiro 实现动态加载权限

    一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...

  5. SpringBoot学习笔记(五):SpringBoot集成lombok工具、SpringBoot集成Shiro安全框架

    SpringBoot集成lombok工具 什么是lombok? 自动生成setget方法,构造函数,打印日志 官网:http://projectlombok.org/features/index. 平 ...

  6. SpringBoot集成Shiro并用MongoDB做Session存储

    之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...

  7. SpringBoot集成Shiro安全框架

    跟着我的步骤:先运行起来再说 Spring集成Shiro的GitHub:https://github.com/yueshutong/shiro-imooc 一:导包 <!-- Shiro安全框架 ...

  8. springboot集成shiro 实现权限控制(转)

    shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...

  9. 【Shiro】SpringBoot集成Shiro

    项目版本: springboot2.x shiro:1.3.2 Maven配置: <dependency> <groupId>org.apache.shiro</grou ...

随机推荐

  1. Jasper:SAOP API 函数

    ylbtech-Jasper:SAOP API 函数 1.设备API返回顶部 1. 设备 设备 API 可以访问详细的设备(SIM 卡)信息,包括当前会话.您也可以更改属性值. API 调用 描述 A ...

  2. [hdu2544]最短路spfa

    解题关键:最短路模板一直没整理过,这里整理了一下spfa+链式前向星建图的最短路模板,以后网络赛省的打了. spfa算法的关键就是松弛操作,只有进行松弛操作,其后的点距离才可能被更新. #includ ...

  3. Servlet拦截匹配规则可以自已定义,拦截哪种URL合适?

    Servlet拦截匹配规则可以自已定义,拦截哪种URL合适? 当映射为@RequestMapping("/user/add")时,为例: 1.拦截*.do.*.htm, 例如:/u ...

  4. JAVA企业级开发-jdbc入门(09)

    一. jdbc介绍 JDBC全称为:Java DataBase Connectivity(java数据库连接). SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JD ...

  5. 使用HTML辅助方法载入分部视图

    在webform中我们用过user control可以减少重复代码也利于将页面模组化, 在mvc中 叫分部视图 Partial View.   也就是一个片段的view.可以利用Partial vie ...

  6. HDU 1506【单调栈】

    思路: 转化成对于某一位置为最小值求向两边最远>=他的位置,用单调栈就能轻易完成. 那么ans=(left+right)*h[i]; 维护单调递增还是递减呢? 我们能很快反应到,一旦碰到一个比他 ...

  7. SP2-0734: 未知的命令开头 “IMP ” - 忽略了剩余的行

    描述 在cmd命令窗口中使用imp命令将dmp文件导入到oracle中时,出现了错误: SP2-0734: 未知的命令开头 “IMP ” - 忽略了剩余的行,如图 原因 imp命令是oracle提供的 ...

  8. 洛谷 P2731 骑马修栅栏 Riding the Fences

    P2731 骑马修栅栏 Riding the Fences 题目背景 Farmer John每年有很多栅栏要修理.他总是骑着马穿过每一个栅栏并修复它破损的地方. 题目描述 John是一个与其他农民一样 ...

  9. js 去除字符串空白符

    var a="      123456" varb=a.replace(/(^\s*)/g, "");

  10. 【填坑】loj6159. 「美团 CodeM 初赛 Round A」最长树链

    水一水 枚举各个质数,把是这个数倍数的点留下,跑直径,没了 #include <bits/stdc++.h> using namespace std; int h,t,n,p,q,M,N; ...