登录风险控制
需求: 获取客户在登录时每次输入的时长,如果相差大,证明可能存在风险!
对输入特征进行采集
首先是获取输入所在的标签对象
<script>
//输入特征采集事件 因为需要等EZui渲染结束所以要加个延时
var timeout= setTimeout(function () {
$("#user_login_form").inputFeatures() //调的自己写的js 事件方法 将标签对象传了过去
clearTimeout(timeout)//清除定时器
},1000)
</script>
<form id="user_login_form" method="post">
<div style="height: 40px;margin-top: 5px;padding: 0 10% 0 10%">
<input class="easyui-textbox" name="name" data-options="required:true,prompt:'用户名',iconCls:'icon-man'" style="height: 100%;width: 100%" >
...密码...
... 验证码 ...
使用传递过来的标签对象,来获取在输入特性(输入所需时间)
$.fn.extend({
inputFeatures: function () {//收集用户的表单输入特征
var input = $(this).find("input");//获取所有的input 标签对象
var futuresMap={}//map 的key 是input 的序列号
$.each(input,function (i, item) {//遍历jQ 选择器选择的元素
$(item).bind("keydown",function (event) {
//为了防止一直按着不动的bug
var start=$(this).data("start")
if(!start){
var start = new Date().getTime();//键盘安下去记一次start
$(this).data("start",start)
}
})
$(item).bind("keyup",function (event) {
var end = new Date().getTime();//键盘弹起一次记一次end
var start=$(this).data("start")
//当按键弹起时如果输入框里没数据就把时间数据给清空了
if($(this).val()==""){
$(this).data("start",null)
futuresMap[i]=0
}else {
futuresMap[i]=end-start
}
var keys=[]
for(var k in futuresMap){//获取futuresMap 所有的键
keys.push(k)
}
//对键进行排序
var sortedKeys= keys.sort();
//获取表单输入特征
// var feature=sortedKeys.map(key=>futuresMap[key]) 这个是下面的遍历简洁写法但有时候可能会不支持
var feature= sortedKeys.map(function (value) {
return futuresMap[value]
})
//将结果用,连接
console.log(feature.join(","))
//创建一个会话Cookie 一旦浏览器关闭,会话消失
$.cookie('feature', feature.join(","), {path: '/'});
})
})
}
})
提醒:
测试时可以用console.log()将输入显示在页面开发者模式的Console 内
将收集到的输入特征传递给后端
思路: 这里需要用到Cookie ,在后台用拦截器获取Cookie 里存的输入特征
我们需要用到Cookie 插件
https://www.runoob.com/jquery/jquery-cookie-plugin.html
有关jQuery Cookie 插件 可以看上面网址参考
首先要在需要的地方
导入<script type="text/javascript" src="/static/common/jquery.cookie.min.js"></script>
在前面的 js 里 创建Cookie
$.cookie('feature', feature.join(","), {path: '/'});
提醒:
如果后面获取不到带数据的这个cookie 需要设置下路径
因为在默认情况下,只有设置 cookie 的网页才能读取该 cookie。
如果想让一个页面读取另一个页面设 置的cookie,必须设置 cookie 的路径。
cookie 的路径用于设置能够读取 cookie 的顶级目录。
将这 个路径设置为网站的根目录,可以让所有网页都能互相读取 cookie (一般不要这样设置,防止出现冲突)。
下面就是在后端拦截器上获取存在cookie 里的输入特征
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
public class LoginInterceptors implements HandlerInterceptor {
private static final Logger LOGGER= LoggerFactory.getLogger(LoginInterceptors.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Cookie[] cookies = request.getCookies();
String decode="";
for (Cookie cookie:cookies){
if (cookie.getName().equals("feature")){
decode = URLDecoder.decode(cookie.getValue());
break;
}
}
// String password = request.getParameter("password");
// String remoteAddr = request.getRemoteAddr();
// String header = request.getHeader("User-Agent");
// LOGGER.debug("password="+password+"\t ip="+remoteAddr+"\t 设备信息"+header);
LOGGER.debug("decode\t"+decode);
return true;
}
}
补充:
其实在拦截器里还可以直接获取用户输入的密码,用户的ip ,用户的设备信息,这都是发起请求时就带有的信息!
String password = request.getParameter("password");
String remoteAddr = request.getRemoteAddr();
String header = request.getHeader("User-Agent");
LOGGER.debug("password="+password+"\t ip="+remoteAddr+"\t 设备信息"+header);
记着设置此拦截器只拦截登录<如何设置请参考另一篇文章《SpringBoot 遗忘后的简单快速回忆之拦截器(和处理用AJAX 异步请求,拦截器的重定向页面无效的问题)》>
//只拦截用户的登录请求
registry.addInterceptor(new LoginInterceptors())
.addPathPatterns("/TextController/userLogin");