Commit 52c0ae50 authored by 董建华's avatar 董建华

新增登陆失败字段

parent dcb47dd5
...@@ -5,6 +5,7 @@ import cn.quantgroup.xyqb.entity.LoginInfo; ...@@ -5,6 +5,7 @@ import cn.quantgroup.xyqb.entity.LoginInfo;
import cn.quantgroup.xyqb.entity.enums.Device; import cn.quantgroup.xyqb.entity.enums.Device;
import cn.quantgroup.xyqb.entity.enums.KeyType; import cn.quantgroup.xyqb.entity.enums.KeyType;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.LoginRefuseResult;
import cn.quantgroup.xyqb.repository.LoginInfoRepository; import cn.quantgroup.xyqb.repository.LoginInfoRepository;
import cn.quantgroup.xyqb.repository.WhiteListRepository; import cn.quantgroup.xyqb.repository.WhiteListRepository;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
...@@ -21,10 +22,9 @@ import org.springframework.web.context.request.ServletRequestAttributes; ...@@ -21,10 +22,9 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* @author :dongjianhua * @author :dongjianhua
...@@ -95,20 +95,24 @@ public class DeviceInterceptorAspect { ...@@ -95,20 +95,24 @@ public class DeviceInterceptorAspect {
deviceId = DEFAULT_CODE; deviceId = DEFAULT_CODE;
} }
if (!verification(scDeviceId, phone)) { LoginRefuseResult result = verification(scDeviceId, phone);
if (!result.isPass()) {
log.warn("登录命中风控策略deviceId:{},phone:{},realIp:{},deviceCode:{}", deviceId, phone, realIp, deviceCode);
return JsonResult.buildErrorStateResult(ALERT_WORDS, null); return JsonResult.buildErrorStateResult(ALERT_WORDS, null);
} }
Object loginResult = null;
/**
* 保存登录信息
*/
saveLoginInfo(phone, deviceCode, deviceId, realIp);
try { try {
return pjp.proceed(); loginResult = pjp.proceed();
} catch (Exception e) { } catch (Exception e) {
throw e; throw e;
} finally {
/**
* 保存登录信息
*/
saveLoginInfo(phone, deviceCode, deviceId, realIp, result, loginResult);
} }
return loginResult;
} }
/** /**
...@@ -116,20 +120,22 @@ public class DeviceInterceptorAspect { ...@@ -116,20 +120,22 @@ public class DeviceInterceptorAspect {
* @param phone * @param phone
* @return * @return
*/ */
private boolean verification(String deviceId, String phone) { private LoginRefuseResult verification(String deviceId, String phone) {
try { try {
/** /**
* 默认code不需要 * 默认code不需要
*/ */
if (DEFAULT_CODE.equals(deviceId)) { if (DEFAULT_CODE.equals(deviceId)) {
return true; return LoginRefuseResult.builder()
.isPass(Boolean.TRUE).build();
} }
/** /**
* 如果没传手机也放过吧 * 如果没传手机也放过吧
*/ */
if (null == phone || "".equals(phone)) { if (null == phone || "".equals(phone)) {
log.warn("怎么没传手机号进来啊暂时放过吧"); log.warn("怎么没传手机号进来啊暂时放过吧");
return true; return LoginRefuseResult.builder()
.isPass(Boolean.TRUE).build();
} }
Long deviceNum = loginInfoRepository.countByDeviceId(deviceId); Long deviceNum = loginInfoRepository.countByDeviceId(deviceId);
...@@ -137,33 +143,55 @@ public class DeviceInterceptorAspect { ...@@ -137,33 +143,55 @@ public class DeviceInterceptorAspect {
if (DEVICE_REFUSE_COUNT.compareTo(deviceNum) < 0) { if (DEVICE_REFUSE_COUNT.compareTo(deviceNum) < 0) {
if (!isWhite(deviceId, KeyType.DEVICEID)) { if (!isWhite(deviceId, KeyType.DEVICEID)) {
log.warn("此设备登录命中拒绝策略,并且未在白名单deviceId:{}超过{}个拒绝登录", deviceId, deviceNum); log.warn("此设备登录命中拒绝策略,并且未在白名单deviceId:{}超过{}个拒绝登录", deviceId, deviceNum);
return true; return LoginRefuseResult.builder()
.isPass(Boolean.TRUE).build();
} }
log.warn("此设备登录命中拒绝策略存在白名单deviceId:{}", deviceId); log.warn("此设备登录命中拒绝策略存在白名单deviceId:{}", deviceId);
return false; return LoginRefuseResult.builder()
.isPass(Boolean.FALSE)
.rule(1)
.threshold(DEVICE_REFUSE_COUNT.intValue())
.value(deviceNum.intValue())
.build();
} }
List<CountDevice> countDevices = loginInfoRepository.countByPhoneAndDevice(phone); List<CountDevice> countDevices = loginInfoRepository.countByPhoneAndDevice(phone);
if (CollectionUtils.isEmpty(countDevices)) { if (CollectionUtils.isEmpty(countDevices)) {
return true; return LoginRefuseResult.builder()
.isPass(Boolean.TRUE)
.build();
} }
/**
* 总数
*/
long sum = countDevices.stream().mapToLong(CountDevice::getNum).sum();
Set<Map.Entry<Device, Long>> entries = DEVICE_REFUSE_STRATEGY.entrySet();
for (Map.Entry<Device, Long> entry : entries) {
for (CountDevice countDevice : countDevices) { Long threshold = entry.getValue();
Long aLong = DEVICE_REFUSE_STRATEGY.get(countDevice.getDevice());
if (null != aLong && countDevice.getNum().compareTo(aLong) > 0) { if (threshold.compareTo(sum) < 0) {
if (!isWhite(deviceId, KeyType.PHONE)) { if (!isWhite(deviceId, KeyType.PHONE)) {
log.warn("此账户登录命中拒绝策略并且没有白名单phone:{},device", phone); log.warn("此账户登录命中拒绝策略并且没有白名单phone:{},device", phone);
return false; return LoginRefuseResult.builder()
.isPass(Boolean.FALSE)
.rule(2)
.threshold(threshold.intValue())
.value(Long.valueOf(sum).intValue())
.build();
} }
log.warn("此账户登录命中拒绝策略存在白名单phone:{}", phone); log.warn("此账户登录命中拒绝策略存在白名单phone:{}", phone);
} }
} }
return true;
} catch (Exception e) { } catch (Exception e) {
log.error("用户登录策略校验异常了", e); log.error("用户登录策略校验异常了", e);
} }
return true; return LoginRefuseResult.builder()
.isPass(Boolean.TRUE)
.build();
} }
/** /**
...@@ -174,7 +202,7 @@ public class DeviceInterceptorAspect { ...@@ -174,7 +202,7 @@ public class DeviceInterceptorAspect {
* @param deviceId * @param deviceId
* @param ip * @param ip
*/ */
private void saveLoginInfo(String phone, String deviceCode, String deviceId, String ip) { private void saveLoginInfo(String phone, String deviceCode, String deviceId, String ip, LoginRefuseResult refuseResult, Object loginResult) {
try { try {
/** /**
* 默认code不需要 * 默认code不需要
...@@ -186,30 +214,37 @@ public class DeviceInterceptorAspect { ...@@ -186,30 +214,37 @@ public class DeviceInterceptorAspect {
Device device = Device.valueOfCode(deviceCode); Device device = Device.valueOfCode(deviceCode);
if (null == device) { LoginInfo info = new LoginInfo();
log.warn("咋回事啊没找到code对应的设备code:{}", deviceCode);
}
Long count = 1L;
LoginInfo info = loginInfoRepository.getFirstByPhoneNoAndDevice(phone, device);
if (null == info) {
info = new LoginInfo();
} else {
count = info.getLoginCount() + 1L;
}
info.setPhoneNo(phone); info.setPhoneNo(phone);
info.setDeviceId(deviceId); info.setDeviceId(deviceId);
info.setLastLoginAt(Timestamp.valueOf(LocalDateTime.now()));//当前时间
info.setDevice(device); info.setDevice(device);
info.setLoginCount(count); info.setIp(ip);
info.setLastIp(ip); info.setIsPass(Boolean.TRUE);
if (!refuseResult.isPass()) {
info.setIsPass(Boolean.FALSE);
info.setHitRule(refuseResult.getRule());
info.setThreshold(refuseResult.getThreshold());
info.setValue(refuseResult.getValue());
}
if (null == loginResult) {
info.setIsLogin(Boolean.FALSE);
} else {
if (loginResult instanceof JsonResult) {
if (((JsonResult) loginResult).isSuccess()) {
info.setIsLogin(Boolean.TRUE);
} else {
info.setIsLogin(Boolean.FALSE);
info.setLoginFailMsg(((JsonResult) loginResult)
.getMsg());
}
}
}
loginInfoRepository.save(info); loginInfoRepository.save(info);
} catch (Exception e) { } catch (Exception e) {
log.error("保存登录信息异常phone:{}", phone, e); log.error("保存登录信息异常phone:{}", phone, e);
......
...@@ -27,7 +27,7 @@ package cn.quantgroup.xyqb.entity; ...@@ -27,7 +27,7 @@ package cn.quantgroup.xyqb.entity;
{ {
@NamedNativeQuery( @NamedNativeQuery(
name = "LoginInfo.countByPhoneAndDevice", name = "LoginInfo.countByPhoneAndDevice",
query = "select count(1) num ,device from login_info where phone_no=?1 and last_login_at> DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL -90 DAY group by device", query = "select count(DISTINCT device_id) num ,device from login_info where phone_no=?1 and created_at > DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL -90 DAY) group by device",
resultClass = CountDevice.class resultClass = CountDevice.class
) )
} }
......
...@@ -30,14 +30,26 @@ public class LoginInfo extends BaseEntity { ...@@ -30,14 +30,26 @@ public class LoginInfo extends BaseEntity {
@Column(name = "device") @Column(name = "device")
private Device device; private Device device;
@Column(name = "last_ip") @Column(name = "ip")
private String lastIp; private String ip;
@Column(name = "login_count") @Column(name = "is_login")
private Long loginCount; private Boolean isLogin;
@Column(name = "last_login_at") @Column(name = "login_fail_msg")
private Timestamp lastLoginAt; private String loginFailMsg;
@Column(name = "is_pass")
private Boolean isPass;
@Column(name = "hit_rule")
private int hitRule;
@Column(name = "threshold")
private int threshold;
@Column(name = "value")
private int value;
/** /**
...@@ -46,16 +58,19 @@ public class LoginInfo extends BaseEntity { ...@@ -46,16 +58,19 @@ public class LoginInfo extends BaseEntity {
* `phone_no` varchar(15) NOT NULL COMMENT '手机号', * `phone_no` varchar(15) NOT NULL COMMENT '手机号',
* `device_id` varchar(50) NOT NULL COMMENT '设备ID', * `device_id` varchar(50) NOT NULL COMMENT '设备ID',
* `device` int(2) DEFAULT NULL COMMENT '设备类型(0安卓,1IOS)', * `device` int(2) DEFAULT NULL COMMENT '设备类型(0安卓,1IOS)',
* `last_ip` varchar(30) DEFAULT NULL COMMENT '同手机设备最后一次登录的IP', * `ip` varchar(30) DEFAULT NULL COMMENT '登录的IP',
* `login_count` int(11) DEFAULT '1' COMMENT '同账户设备登录次数', * `is_login` int(1) DEFAULT '1' COMMENT '是否登录成功',
* `last_login_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次登陆时间', * `is_pass` int(1) DEFAULT '1' COMMENT '是否通过风控策略',
* `hit_rule` int(1) DEFAULT '0' COMMENT '命中的规则',
* `threshold` int(3) DEFAULT NULL COMMENT '阈值',
* `value` int(10) DEFAULT '0' COMMENT '实际的值',
* `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(第一次登陆时间)', * `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(第一次登陆时间)',
* `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', * `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
* PRIMARY KEY (`id`), * PRIMARY KEY (`id`),
* UNIQUE KEY `phone_deviceid_idx` (`phone_no`,`device_id`) USING BTREE,
* KEY `deviceid_idx` (`device_id`) USING BTREE, * KEY `deviceid_idx` (`device_id`) USING BTREE,
* KEY `create_at_idx` (`created_at`) USING BTREE, * KEY `create_at_idx` (`created_at`) USING BTREE,
* KEY `last_login_at_idx` (`last_login_at`) USING BTREE * KEY `updated_at_idx` (`updated_at`) USING BTREE,
* KEY `phone_idx` (`phone_no`) USING BTREE
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='登录信息表'; * ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='登录信息表';
*/ */
} }
...@@ -7,7 +7,9 @@ public enum Device { ...@@ -7,7 +7,9 @@ public enum Device {
ANDROID("安卓", "android"), ANDROID("安卓", "android"),
IOS("IOS", "ios"); IOS("IOS", "ios"),
OTHER("other","other"),
;
private String desc; private String desc;
private String code; private String code;
...@@ -19,7 +21,7 @@ public enum Device { ...@@ -19,7 +21,7 @@ public enum Device {
public static Device valueOfCode(String code) { public static Device valueOfCode(String code) {
if(null == code){ if(null == code){
return null; return Device.OTHER;
} }
for (Device device : Device.values()) { for (Device device : Device.values()) {
if (device.code.equals(code)) { if (device.code.equals(code)) {
......
package cn.quantgroup.xyqb.model;
import lombok.Builder;
import lombok.Data;
/**
* @author :dongjianhua
* @date :Created in 2020/11/23 15:07
* @description:拒绝结果
* @modified By:
* @version:
*/
@Data
@Builder
public class LoginRefuseResult {
private int rule;
private int threshold;
private int value;
private boolean isLogin;
private boolean isPass;
}
...@@ -16,7 +16,7 @@ public interface LoginInfoRepository extends JpaRepository<LoginInfo, Long> { ...@@ -16,7 +16,7 @@ public interface LoginInfoRepository extends JpaRepository<LoginInfo, Long> {
* @param deviceId 设备维度策略 * @param deviceId 设备维度策略
* @return * @return
*/ */
@Query(value = "select count(1) from login_info where device_id=?1 and last_login_at> DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL -90 DAY)", nativeQuery = true) @Query(value = "select count(distinct device_id) from login_info where device_id=?1 and created_at> DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL -90 DAY)", nativeQuery = true)
Long countByDeviceId(String deviceId); Long countByDeviceId(String deviceId);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment