概述
登陆位移计算也就是计算当前登陆的位置与上次登陆的位置的距离与速度,根据当前速度与一个当今社会的正常交通速度相比较,如果速度过大就可以视为有盗号风险。
球面距离计算公式
A地:(经度:Aj,纬度:Aw)B地:(经度:Bj,纬度:Bw)两地距离:
数据支持
评估数据 登陆时间,登陆地区经纬度历史数据 上一次登陆时间,上一次登陆经纬度
java代码示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GeoPoint implements Serializable {
private double longtitude;//经度
private double latitude;//纬度
}
/**
* 异地登录判断
* 位移速度计算
*/
public class SpeedEvaluate {
private static final Double EARTH_RADIUS = 6371.393;//地球半径
private Double thresholdSpeed;//阈值速度,超过该速度被认定为有盗号风险
public SpeedEvaluate(Double thresholdSpeed){
this.thresholdSpeed = thresholdSpeed;
}
/**
* 登陆位移速度计算
* @param loginTime 本次登陆时间
* @param loginGeoPoint 本次登陆经纬度
* @param lastLoginTime 上次登陆时间
* @param lastLoginGeoPoint 上次经纬度
*/
public Boolean doEval(Long loginTime, GeoPoint loginGeoPoint,Long lastLoginTime,GeoPoint lastLoginGeoPoint){
//用户第一次登陆
if (lastLoginTime == null){
return false;
}
//计算两地球面距离
Double distance = calculateDistanceByGeoPoint(loginGeoPoint, lastLoginGeoPoint);
System.out.println("两地距离:" + distance);
//计算速度
Double speed = distance / (((loginTime - lastLoginTime) * 1.0 )/(3600*1000));
System.out.println("速度:" + speed);
return speed > thresholdSpeed;
}
/**
* 根据两地经纬度计算距离
* @param g1
* @param g2
* @return
*/
public Double calculateDistanceByGeoPoint(GeoPoint g1,GeoPoint g2){
//把经纬度转换为弧度制
double w1 = toRadians(g1.getLatitude());//纬度1
double j1 = toRadians(g1.getLongtitude());//经度1
double w2 = toRadians(g2.getLatitude());//纬度2
double j2 = toRadians(g2.getLongtitude());//经度2
//利用公式计算两地距离
return EARTH_RADIUS * acos(cos(w1)*cos(w2)*cos(j1 - j2) + sin(w1)*sin(w2));
}
//测试
public static void main(String[] args) throws ParseException {
SpeedEvaluate speedEvaluate = new SpeedEvaluate(600.0);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long evaluateTime=sdf.parse("2020-04-01 10:10:00").getTime();
GeoPoint p1=new GeoPoint();
p1.setLongtitude(116.2317);//北京
p1.setLatitude(39.5427);
long lastLoginTime=sdf.parse("2020-04-01 08:00:00").getTime();
GeoPoint p2=new GeoPoint();
p2.setLongtitude(114.14);//郑州
p2.setLatitude(34.16);
speedEvaluate.doEval(evaluateTime,p1,lastLoginTime,p2);
}
}