在企业级应用开发中,不可缺失的一个微服务/模块就是登陆校验。常规的有:用户名/密码验证,加强版的有:密码加盐混淆验证外。考虑到密码泄露类事件的时有发生,以及因为计算机技术发展产生的黑客暴力枚举破解的算力加持。故而,需要在用户名/密码校验基础上,增加更高级的校验,一般来说有三类:图片验证码,手机短信,邮箱验证码;其中图片验证码又有滑动图片验证码。
如数字密码,4位数字,实际上可穷举,10000种可能性暴力破解。
安全意识较强的网站,此时一般会设置允许错误的次数,如3/5次错误即触发账户锁定1小时或者5小时不定,防止密码被暴力破解的隐患。
原理就是生成一张指定尺寸规格的图片,在图片里面有4位或者多位数字,为了应对发展日益成熟的人工智能图片识别技术,加入混淆元素,一定程度上可以防止机器识别。
CAPTCHA,Completely Automated Public Turing test to tell Computers and Humans Apart,全自动区分计算机和人类的图灵测试,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
可以自研,不过推荐使用开源技术,如谷歌验证码工具kaptcha。
Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项:
Kaptcha官网
GitHub
maven依赖:
<dependency>
<groupId>com.google.code.kaptchagroupId>
<artifactId>kaptchaartifactId>
<version>2.3version>
dependency>
google官方提供的 pom 无法正常使用,使用阿里云仓库对应 kaptcha:
<dependency>
<groupId>com.github.pengglegroupId>
<artifactId>kaptchaartifactId>
<version>2.3.2version>
dependency>
配置类:com.google.code.kaptcha.util.Config,自带默认值,支持配置修改
com.google.code.kaptcha.impl.WaterRipple
,鱼眼com.google.code.kaptcha.impl.FishEyeGimpy
,阴影com.google.code.kaptcha.impl.ShadowGimpy
使用方式:
@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDDefaultKaptcha() {
DefaultKaptcha dk = new DefaultKaptcha();
Properties properties = new Properties();
// 图片边框
properties.setProperty("kaptcha.border", "yes");
Config config = new Config(properties);
dk.setConfig(config);
return dk;
}
}
kaptchaConfig.xml
文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
<property name="config">
<bean class="com.google.code.kaptcha.util.Config">
<constructor-arg type="java.util.Properties">
<props>
<prop key="kaptcha.border">yesprop>
props>
constructor-arg>
bean>
property>
bean>
beans>
然后引入配置类@ImportResource(locations={"classpath:kaptchaConfig.xml"})
定义Controller:
/**
* 验证码工具
*/
@Autowired
private DefaultKaptcha defaultKaptcha;
@RequestMapping("/validate")
public void defaultKaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
byte[] captcha;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
// 将生成的验证码保存在session中或Redis
String createText = defaultKaptcha.createText();
request.getSession().setAttribute("rightCode", createText);
BufferedImage bi = defaultKaptcha.createImage(createText);
ImageIO.write(bi, "jpg", out);
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
captcha = out.toByteArray();
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
ServletOutputStream sout = response.getOutputStream();
sout.write(captcha);
sout.flush();
sout.close();
}
/**
* 校对验证码
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView imgvrifyControllerDefaultKaptcha(HttpServletRequest request, HttpServletResponse response) {
ModelAndView model = new ModelAndView();
String rightCode = (String) request.getSession().getAttribute("rightCode");
String tryCode = request.getParameter("tryCode");
if (!rightCode.equals(tryCode)) {
model.addObject("info", "验证码错误,请再输一次!");
model.setViewName("login");
} else {
model.addObject("info", "登陆成功");
model.setViewName("index");
}
return model;
}
另外你可能会看到一个easy-captcha项目,和google kaptcha没有半毛钱关系。看到easy,哈哈,你没猜错,确实是国人"开源"的项目。文档还算丰富。
EasyCaptcha-GitHub
<dependency>
<groupId>com.github.whvcsegroupId>
<artifactId>easy-captchaartifactId>
<version>1.6.2version>
dependency>
使用:
// deviceId是前端生成的随机字符串,用于验证码存储于Redis时生成key
@GetMapping("/code/{deviceId}")
public void createCode(@PathVariable String deviceId, HttpServletResponse response) throws Exception {
Assert.notNull(deviceId, "机器码不能为空");
// 设置请求头为输出图片类型
CaptchaUtil.setHeader(response);
// 三个参数分别为宽、高、位数
Captcha captcha = new SpecCaptcha(100, 35, 4);
// 设置类型:字母数字混合
captcha.setCharType(Captcha.TYPE_DEFAULT);
// 保存验证码,存储于Redis
validateCodeService.saveImageCode(deviceId, captcha.text().toLowerCase());
// 输出图片流
captcha.out(response.getOutputStream());
}
逻辑:根据鼠标滑动轨迹,坐标位置,拖动速度等来判断是否人为操作。
核心流程:
https://www.jb51.net/article/126777.htm
https://www.cnblogs.com/yaohonv/p/swipecaptcha.html
安全性比图片验证码高,
安全性比图片验证码高,
https://github.com/fightingape/sailing
腾讯云短信服务
需要注册腾讯云开通短信服务:
https://cloud.tencent.com/product/isms/getting-started
开通短信服务成功后,获取 SDKAppID 和 AppKey,云短信应用 SDKAppID 和 AppKey 可在 短信控制台 的应用信息里获取。
申请签名并确认审核通过 一个完整的短信由短信签名和短信正文内容两部分组成,短信签名需申请和审核,签名可在 短信控制台的相应服务模块【内容配置】中进行申请,详细申请操作请参见 创建签名。发送国际短信时,允许不携带签名。
申请模板并确认审核通过 短信或语音正文内容模板需申请和审核,模板可在 短信控制台 的相应服务模块【内容配置】中进行申请,详细申请操作请参见 创建正文模板。
手势密码,实际上是从1~9选出若干个数字形成密码,且数字可以相连,弱化版的数字密码。手势密码设置的规则:密码不小于4个点,点在第一次经过时不允许被跳过。
直接抛结论,各个数字的个数的可能性:
参考手势密码有几种?
Two-Factor Authentication,2FA,最早得知于GitHub网站。
从密码学理论上说,用于身份认证主要有三方面要素:
单独来看,每个要素独立存在时,都有其脆弱性。而把两种要素结合起来,实现双重要素认证,可以有效提高系统访问控制的安全性,就是双因素认证。双因素认证是一种适合企业的访问控制策略,它将访问控制过程中个人身份识别更客观化,有效地防止来自外部的身份欺诈和来自内部的更隐蔽的网络侵犯。一般的企业都有标识身份的员工IC卡,可以利用这张卡来实现双因素认证。基于过多增加企业信息化成本的角度出发,以下方案采用的是员工卡IC卡+用户密码来进行安全访问控制。
参考gitlab_two_factor_authentication
每个人的指纹都不一样,满足唯一性。
缺点:
参考指纹识别-百度百科
目前的人脸识别与经验系统,大多数情况下只是作为一个活体检测,
参考
缺点:
https://picsum.photos/
https://www.jianshu.com/p/22004d424183
kaptcha谷歌验证码工具
springboot 集成kaptcha验证码Demo
https://www.jianshu.com/p/a3525990cd82