大数据板块设计(阶段2)
用户登陆风险评估
检查出⾮⽤户登录,或者账号被盗窃等潜在⻛险挖掘。 通过对用户登录行为进行分析,提高了预测的准确性;可以应用于互联网金融风控技术中,也可应用于普通网站的用户恶意登录识别技术中
- 异地登录认定有⻛险(不在⽤户经常登陆地)
- 登录的位移速度超过正常值,认定有⻛险
- 更换设备,认定有⻛险
- 登录时段-习惯,出现了异常,存在⻛险
- 每天的累计登录次数超过上限,认定有⻛险
- 密码输⼊错误或者输⼊差异性较⼤,认定⻛险
- 如果⽤户的输⼊特征(输⼊每个控件所需时⻓ ms)发⽣变化
参考:https://zhuanli.tianyancha.com/796c88e9c3d67d3a9c59716558818e22
算法实现概述
一种基于用户登录行为分析的风控方法,其特征在于:所述的方法包括用户按键风险识别
、用户登录地风险识别
、密码重试风险识别
、设备来源风险识别
用户登陆习惯风险识别
累计登陆多次风险识别
用户登陆的瞬时位移速度风险识别其中模型;本系统仅仅负责根据用户的登陆数据产生风险评估报告.报告的格式为:
应用信息 | 用户唯一标识 | 登陆地区 | 经纬度 | 登陆序列号 | 评估时间 | 输入特征 | 地区 | 速度 | 设备 | 习惯 | 次数 | 密码 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
zhangsan | Beijing | 116.20,39.56 | UUID | 2020-03.31 10:10:00 | ture | false | true | false | true | false | true |
并不负责对用户的登陆做出定性的分析,仅仅当用户登陆数据过来,由大数据评估系统对用户数据进行评估,然后产生评估报告.由业务系统自行根据评估报告,需用用户采用相关的奖惩措施.介于以上评估报告系统需要用户发送以下数据格式,以辅助系统完成验证:
需要评估登陆数据: 用于本次登陆前产生评估报告的数据.系统拿到评估报告以后,再去做抉择是否升级登陆 该数据需要获取用户的历史登陆成功的数据集合
完成评估.
INFO 2020-03-31 10:12:00 QQ EVALUATE [张三] 6ebaf4ac780f40f486359f3ea6934620 "12355421" Beijing "116.4,39.5" [1200,15000,2100] "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
需要成功产生数据: 登陆成功的数据用来作为下一次评估登陆时的历史数据,系统留存最近的一些历史登陆数据集,作为下一次登陆评估的标准
INFO 2020-03-31 10:12:00 QQ EVALUATE [张三] 6ebaf4ac780f40f486359f3ea6934620 "12355421" Beijing "116.4,39.5" [1200,15000,2100] "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
数据提取
Tip:https://regex101.com/ -工具
d:表示匹配数字
():提取的内容
\u4e00-\u9fa5:中文
INFO 2020-03-31 10:12:00 QQ EVALUATE [张三] 6ebaf4ac780f40f486359f3ea6934620 "12355421" Beijing "116.4,39.5" [1200,15000,2100] "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
import java.util.regex.Matcher;
import java.util.regex.Pattern;
final String regex = "^INFO\\s\\d{4}-(\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})\\s([a-z0-9]*)\\s(EVALUATE|SUCCESS)\\s(\\[[a-z0-9\\u4e00-\\u9fa5]*\\])\\s([a-z0-9]{32})\\s(\\\"[a-z0-9]{6,12}\\\")\\s([a-z\\u4e00-\\u9fa5]*)\\s\\\"([0-9\\.\\,]*)\\\"\\s\\[([0-9\\,\\.]*)\\]\\s\\\"(.*)\\\"";
final String string = "INFO 2020-03-31 10:12:00 QQ EVALUATE [张三] 6ebaf4ac780f40f486359f3ea6934620 \"12355421\" Beijing \"116.4,39.5\" [1200,15000,2100] \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36\"";
final Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
测试结果
Full match:INFO 2020-03-31 10:12:00 QQ EVALUATE [张三] 6ebaf4ac780f40f486359f3ea6934620 "12355421" Beijing "116.4,39.5" [1200,15000,2100] "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
Group1:2020-03-31 10:12:00
Group2:QQ
Group3:EVALUATE
Group4:张三
Group5:6ebaf4ac780f40f486359f3ea6934620
Group6:12355421
Group7:Beijing
Group8:116.4,39.5
Group9:1200,15000,2100
Process finished with exit code 0
- 把登陆的日志变成评估的实体类
/**
* 2020-03-31 10:12:00 QQ EVALUATE [张三]
* 6ebaf4ac780f40f486359f3ea6934620 "12355421"
* Beijing "116.4,39.5" [1200,15000,2100]
* "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
* */
//评估类
public class EvaluateData implements Serializable {
private long evaluateTime;//评估时间
private String applicationName;//应用名
private String userIdentify;//用户的唯一标识
private String loginSequence;//登陆序列
private String ordernessPassword;//乱序密码
private String cityName;//城市名字
private GeoPoint geoPoint;//经纬度
private Double[] inputFeatures;//输入特征
private String deviceInformation;//登陆设备
- 提供set get 有参无参 toString方法
- 经纬度实体类
public class GeoPoint {
private double longtitude;//经度
private double latitude;//纬度
- 登陆成功的数据类
//登陆成功的数据
public class LoginSuccessData implements Serializable {
private long evaluateTime;//评估时间
private String applicationName;//应用名
private String userIdentify;//用户识别
private String loginSequence;
private String ordernessPassword;//
private String cityName;//城市名字
private GeoPoint geoPoint;//经纬度
private Double[] inputFeatures;//输入特征
private String deviceInformation;//登陆设备
- 历史数据-将来历史数据和评估数据之间进行评估
/**
* 记录用户登陆的历史状态
* */
public class HistoryData implements Serializable {
//保存用户所登陆的历史城市
private Set<String> historyCities;
//历史的登陆设备信息
private List<String> historyDeviceInformations;
//当日登录的累计次数 -作为单独状态存储 不在update中实现(在流中记录当前用户登录的次数)
private Integer currentDayLoginCount;
//存储用户历史的乱序密码
private Set<String> historyOrdernessPasswords;
//用户输入特征更新 保留最近的前n个
private List<Double[]> latestInputFeatures;
//更新登录时间
private long lastLoginTime;
//上一次登录位置更新
private GeoPoint lastLoginGeoPoint;//经纬度
//历史登录的时间区间
private Map<String, Map<String, Integer>> historyLoginTimeSlot;
@Override
public String toString() {
return "HistoryData{" +
"historyCities=" + historyCities +
", historyDeviceInformations=" + historyDeviceInformations +
", currentDayLoginCount=" + currentDayLoginCount +
", historyOrdernessPasswords=" + historyOrdernessPasswords +
", latestInputFeatures=" + latestInputFeatures.stream().map(v-> Arrays.stream(v).map(a->a+"").reduce((v1,v2)->v1+","+v2).get()).collect(Collectors.toList()) +
", lastLoginTime=" + lastLoginTime +
", lastLoginGeoPoint=" + lastLoginGeoPoint +
", historyLoginTimeSlot=" + historyLoginTimeSlot +
'}';
}
public Set<String> getHistoryCities() {
return historyCities;
}
public void setHistoryCities(Set<String> historyCities) {
this.historyCities = historyCities;
}
public List<String> getHistoryDeviceInformations() {
return historyDeviceInformations;
}
public void setHistoryDeviceInformations(List<String> historyDeviceInformations) {
this.historyDeviceInformations = historyDeviceInformations;
}
public Integer getCurrentDayLoginCount() {
return currentDayLoginCount;
}
public void setCurrentDayLoginCount(Integer currentDayLoginCount) {
this.currentDayLoginCount = currentDayLoginCount;
}
public Set<String> getHistoryOrdernessPasswords() {
return historyOrdernessPasswords;
}
public void setHistoryOrdernessPasswords(Set<String> historyOrdernessPasswords) {
this.historyOrdernessPasswords = historyOrdernessPasswords;
}
public List<Double[]> getLatestInputFeatures() {
return latestInputFeatures;
}
public void setLatestInputFeatures(List<Double[]> latestInputFeatures) {
this.latestInputFeatures = latestInputFeatures;
}
public long getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(long lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public GeoPoint getLastLoginGeoPoint() {
return lastLoginGeoPoint;
}
public void setLastLoginGeoPoint(GeoPoint lastLoginGeoPoint) {
this.lastLoginGeoPoint = lastLoginGeoPoint;
}
public Map<String, Map<String, Integer>> getHistoryLoginTimeSlot() {
return historyLoginTimeSlot;
}
public void setHistoryLoginTimeSlot(Map<String, Map<String, Integer>> historyLoginTimeSlot) {
this.historyLoginTimeSlot = historyLoginTimeSlot;
}
}
- 定义一个Evaluate工具类
public class EvalueateUtil {
//合法正则表达式
public static final String LEGAL_REGEX = "^INFO\\s(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})\\s([a-z0-9\\u4e00-\\u9fa5]*)\\s(EVALUATE|SUCCESS)\\s\\[([a-z0-9\\u4e00-\\u9fa5]*)\\]\\s([a-z0-9]{32})\\s\\\"([a-z0-9\\.\\-\\,]{6,12})\\\"\\s([a-z\\u4e00-\\u9fa5]*)\\s\\\"([0-9\\.\\,]*)\\\"\\s\\[([0-9\\,\\.]*)\\]\\s\\\"(.*)\\\"";
//评估正则表达式 只能是EVALUATE
public static final String EVALUATE_REGEX = "^INFO\\s(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})\\s([a-z0-9\\u4e00-\\u9fa5]*)\\s(EVALUATE)\\s\\[([a-z0-9\\u4e00-\\u9fa5]*)\\]\\s([a-z0-9]{32})\\s\\\"([a-z0-9\\.\\-\\,]{6,12})\\\"\\s([a-z\\u4e00-\\u9fa5]*)\\s\\\"([0-9\\.\\,]*)\\\"\\s\\[([0-9\\,\\.]*)\\]\\s\\\"(.*)\\\"";
//成功正则表达式
public static final String SUCCESS_REGEX = "^INFO\\s(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})\\s([a-z0-9\\u4e00-\\u9fa5]*)\\s(SUCCESS)\\s\\[([a-z0-9\\u4e00-\\u9fa5]*)\\]\\s([a-z0-9]{32})\\s\\\"([a-z0-9\\.\\-\\,]{6,12})\\\"\\s([a-z\\u4e00-\\u9fa5]*)\\s\\\"([0-9\\.\\,]*)\\\"\\s\\[([0-9\\,\\.]*)\\]\\s\\\"(.*)\\\"";
public static final Pattern LEGAL_PATTERN = Pattern.compile(LEGAL_REGEX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
public static final Pattern EVALUATE_PATTERN = Pattern.compile(EVALUATE_REGEX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
public static final Pattern SUCCESS_PATTERN = Pattern.compile(SUCCESS_REGEX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
final static String regex = "^INFO\\s(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})\\s([a-z0-9\\u4e00-\\u9fa5]*)\\s(EVALUATE|SUCCESS)\\s\\[([a-z0-9\\u4e00-\\u9fa5]*)\\]\\s([a-z0-9]{32})\\s\\\"([a-z0-9\\.\\-\\,]{6,12})\\\"\\s([a-z\\u4e00-\\u9fa5]*)\\s\\\"([0-9\\.\\,]*)\\\"\\s\\[([0-9\\,\\.]*)\\]\\s\\\"(.*)\\\"";
final static String string = "INFO 2020-03-31 10:12:00 Q1Q应用1 success [张三] 6ebaf4ac780f40f486359f3ea6934620 \"123456\" Beijing \"116.4,39.5\" [1200,15000,2100] \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36\"";
//判断登陆是否合法调用此方法
public static Boolean isLegal(String input) {
Matcher matcher = LEGAL_PATTERN.matcher(input);
return matcher.matches();
}
//评估
public static Boolean isEvaluate(String input) {
Matcher matcher = EVALUATE_PATTERN.matcher(input);
return matcher.matches();
}
//是否是登陆成功的数据
public static Boolean isLoginSuccess(String input) {
Matcher matcher = SUCCESS_PATTERN.matcher(input);
return matcher.matches();
}
//
public static EvaluateData parseE