SpringBoot+使用过滤器链执行风控决策
风控流程

下单前进行风控校验
// 1.begin---风控处理---前置处理{黑白名单校验}
RiskControlRuleEnum controlRuleEnum = riskControlHandlerService.preHandle(mappingObj.getMerchantGoodsType(), thatUser);
if (controlRuleEnum != null) {
logger.error("风控处理进入--->{}", controlRuleEnum.getDesc());
Result error = Result.error(controlRuleEnum.getDesc());
error.setCode("WEB_RISK_CONTROL_" + controlRuleEnum.getCode());
return error;
}
下单后进行风控判断是否会进入
// 2.ending---风控限制后置处理|处理{黑白名单校验}
taskExecutor.execute(() -> riskControlHandlerService.afterBuyingTicketsHandle(mappingObj.getMerchantGoodsType(), user));
风控前置校验
/**
* 风控---前置校验
*
* @param user user
* @return
* @throws Exception
*/
public RiskControlRuleEnum preHandle(String merchantGoodsType, User user) {
// 风控规则校验---拒绝购买票的号码校验
List<RiskControlManager> managerList = riskControlManagerService.getByMerchantGoodsType(merchantGoodsType);
if (CollectionUtils.isNotEmpty(managerList)) {
for (RiskControlManager manager : managerList) {
// 拒绝号码购买----风控校验
String riskControlDesc = manager.getRiskControlDesc();
if (StringUtils.isNotBlank(riskControlDesc)) {
String[] splitPhone = riskControlDesc.split(",");
for (String thatLimitPhone : splitPhone) {
if (StringUtils.isNotBlank(user.getMobile()) && user.getMobile().startsWith(thatLimitPhone)) {
return RiskControlRuleEnum.TicketPurchaseProhibited;
}
}
}
}
}
RiskControlUsers riskControlUsers = new RiskControlUsers();
riskControlUsers.setPayerId(user.getMid());
riskControlUsers.setMerchantGoodsType(merchantGoodsType);
List<RiskControlUsers> riskControlUsers1 = riskControlUsersService.listAll(riskControlUsers);
if (CollectionUtils.isEmpty(riskControlUsers1)) {
return null;
}
// 如果有黑名单限制--黑名单限制
for (RiskControlUsers controlUsers : riskControlUsers1) {
if (controlUsers.getRiskControlLimitType().equals(RiskControlRuleEnum.TicketPurchaseProhibited.getCode())) {
return RiskControlRuleEnum.TicketPurchaseProhibited;
}
}
// 如果没有黑名单限制--灰名单限制
Integer riskControlLimitType = riskControlUsers1.get(0).getRiskControlLimitType();
RiskControlRuleEnum[] values = RiskControlRuleEnum.values();
for (RiskControlRuleEnum ruleEnum : values) {
if (ruleEnum.getCode().equals(riskControlLimitType)) {
return ruleEnum;
}
}
return null;
}
风控后置--决策
/**
* 风控----后置校验
*
* @param user user
* @return
* @throws Exception
*/
public void afterBuyingTicketsHandle(String merchantGoodsType, User user) {
// 商品维度的风控策略加载||已启用的加商品类型过滤+优先级排序
List<RiskControlManager> managerList = riskControlManagerService.getByMerchantGoodsType(merchantGoodsType);
if (CollectionUtils.isEmpty(managerList)) {
return;
}
RiskControlDecisionsFilterChain filterChain = RiskControlDecisionsFilterChain.getInstance();
// 获取用户风控信息{已经SQL的排序修改按照序列的--优先级排序}
for (RiskControlManager manager : managerList) {
Long mid = manager.getMid();
// 获取风控惩罚机制
RiskControlRestrictive riskControlRestrictive = new RiskControlRestrictive();
riskControlRestrictive.setRiskControlRuleId(mid);
List<RiskControlRestrictive> restrictives = riskControlRestrictiveService.listAll(riskControlRestrictive);
if (CollectionUtils.isEmpty(restrictives)) {
// 如果没有--风控策略
continue;
}
// 风控排序 -----最小条件满足优先{天--小时---分钟}
Comparator<RiskControlRestrictive> comparator = new Comparator<RiskControlRestrictive>() {
@Override
public int compare(RiskControlRestrictive o1, RiskControlRestrictive o2) {
// 时间间隔单位
Integer timeIntervalUnitV1 = o1.getTimeIntervalUnit();
Integer timeIntervalUnitV2 = o2.getTimeIntervalUnit();
return timeIntervalUnitV1 - timeIntervalUnitV2;
}
};
restrictives.sort(comparator);
// 校验用户风控策略满足条件{过滤器链路使用---用户封印{无法根据IP、身份证、电话号码封印}}
for (RiskControlRestrictive restrictive : restrictives) {
// 获取限制类型---下单的限定
if (restrictive.getOperationType().equals(RiskControlRestrictiveOperationEnum.PlaceAnOrder.getCode())) {
// 风控决策引擎--启动{决策目标风控行为:开启所有的风控链决策--使用 execute 方法}
boolean execute = filterChain.executeDefaultHandler(user, manager, restrictive, riskControlLimitAccountFilterChain);
if (execute) {
// 满足风控条件任意一项:黑白名单入库成功---------风控过滤链释放
return;
}
} else if (restrictive.getOperationType().equals(RiskControlRestrictiveOperationEnum.Refund.getCode())) {
// 获取限制类型---退款的限定--todo
}
}
}
}
风控决策引擎管理--总线
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎
*/
public class RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlDecisionsFilterChain.class);
/**
* 标识===过滤器所属限制类型
* 子类必须重写
*
* @return int
*/
protected int getThisRestrictiveType() {
return 0;
}
/**
* 风控决策过滤器链
*/
public static List<RiskControlDecisionsFilterChain> filterChains = new ArrayList<>();
private static RiskControlDecisionsFilterChain chain = null;
public static RiskControlDecisionsFilterChain getInstance() {
if (chain == null) {
synchronized (RiskControlDecisionsFilterChain.class) {
if (chain == null) {
chain = new RiskControlDecisionsFilterChain();
}
}
}
return chain;
}
/**
* 风控决策引擎执行入口
*
* @param user 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
log.error("风控决策引擎执行-----进入执行---------");
for (RiskControlDecisionsFilterChain filterChain : filterChains) {
// 获取限制类型----只运行当前限制的决策事件
if (restrictive.getRestrictiveType().equals(filterChain.getThisRestrictiveType())) {
// 获取执行链路的结果
boolean respWasSuccess = filterChain.execute(user, manager, restrictive);
// 已经执行成功,则过滤器链终止
if (respWasSuccess) {
return true;
}
}
}
log.error("风控决策引擎执行-----执行结束---------");
return false;
}
protected int countRiskControlLimit(String startTime, String endTime, User user) {
return 0;
}
/**
* 保存用户--进入限制桶
* 子类必须重写
*
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
}
protected ReleaseTimeSetting getReleaseTimeSetting() {
return null;
}
/**
* 限制名单限定--决策----通用业务逻辑
*
* @param user userId
* @param manager manager
* @param restrictive restrictive
*/
protected boolean executeDefaultHandler(User user, RiskControlManager manager, RiskControlRestrictive restrictive, RiskControlDecisionsFilterChain targetFilterChain) {
// 获取时间间隔
Long timeInterval = restrictive.getTimeInterval();
// 获取时间间隔单位
Integer timeIntervalUnit = restrictive.getTimeIntervalUnit();
// 获取限制次数
Long quantity = restrictive.getQuantity();
// 计算限制区间:当前时间 -- 开始时间
LocalDateTime now = LocalDateTime.now();
String endTime = LocalDateTimeUtil.format(now, RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
String startTime = null;
if (timeIntervalUnit.equals(RiskControlRestrictiveTimeEnum.Minute.getCode())) {
// 如果是分钟
startTime = LocalDateTimeUtil.format(now.minusMinutes(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
} else if (timeIntervalUnit.equals(RiskControlRestrictiveTimeEnum.Hours.getCode())) {
// 如果是小时
startTime = LocalDateTimeUtil.format(now.minusHours(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
} else {
// 天
startTime = LocalDateTimeUtil.format(now.minusDays(timeInterval), RuleCommonUtils.YYYY_MM_DD_HH_MM_SS);
}
// 查询当前情况下的下单数量
int thatOrderNum = targetFilterChain.countRiskControlLimit(startTime, endTime, user);
if (thatOrderNum >= quantity) {
log.error("用户{}在{}到{}期间下单次数超过限制次数{}", user.getMid(), startTime, endTime, quantity);
// 封印该用户--todo{惩罚机制}
RiskControlUsers riskControlUsers = new RiskControlUsers();
riskControlUsers.setStateId(1);
riskControlUsers.setCreateTime(new Date());
riskControlUsers.setMerchantGoodsType(manager.getMerchantGoodsType());
riskControlUsers.setRiskControlDetailLimit(manager.getRiskControlDetailLimit());
riskControlUsers.setRiskControlLimitType(manager.getRiskControlRule());
ReleaseTimeSetting releaseTimeSetting = targetFilterChain.getReleaseTimeSetting();
if (releaseTimeSetting != null) {
riskControlUsers.setReleaseTimeDay(releaseTimeSetting.getNowDay());
} else {
riskControlUsers.setReleaseTimeDay(7);
}
riskControlUsers.setRiskControlCardType("身份证");
riskControlUsers.setIdCard(user.getIdentityNumber());
// 黑名单|白名单
riskControlUsers.setRiskControlTypeName(manager.getRiskControlRestrictive());
riskControlUsers.setUserName(user.getName());
riskControlUsers.setPhone(user.getMobile());
riskControlUsers.setIpAddres(user.getLastLoginIP());
riskControlUsers.setLimitTime(new Date());
riskControlUsers.setDescLimit(manager.getRiskControlName());
riskControlUsers.setPayerId(user.getMid());
log.error("风控----管控---用户信息------>:" + JSONObject.toJSONString(riskControlUsers));
targetFilterChain.saveLimitUser(riskControlUsers);
return true;
}
return false;
}
}
风控链----01风控决策引擎---限制账户
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制账户
*/
@Component
public class RiskControlLimitAccountFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitAccountFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitAccount.getCode();
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitAccountFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制账户
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
return orderService.countRiskControlLimit(startTime, endTime, user.getMid());
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----02风控决策引擎---限制身份证
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制身份证
*/
@Component
public class RiskControlLimitIdCardFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitIdCardFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitIdCard.getCode();
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitIdCardFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制身份证
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String identityNumber = user.getIdentityNumber();
if (StringUtils.isBlank(identityNumber)) {
return 0;
}
return orderService.countRiskControlFiledLimit(startTime, endTime, identityNumber);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----03风控决策引擎---限制账IP
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制IP
*/
@Component
public class RiskControlLimitIpFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitIpFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitIpFilterChain() {
filterChains.add(this);
}
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitIp.getCode();
}
/**
* 风控决策引擎执行入口--限制IP
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String lastLoginIP = user.getLastLoginIP();
if (StringUtils.isBlank(lastLoginIP)) {
return 0;
}
return orderService.countRiskControlIPLimit(startTime, endTime, lastLoginIP);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
风控链----04风控决策引擎---限制手机
/**
* packageName com.cztech.platform.transaction.common.riskControl
*
* @author GuoTong
* @version JDK 8
* @className RiskControlDecisionsFilterChain
* @date 2024/5/9
* @description 风控决策引擎---限制手机号
*/
@Component
public class RiskControlLimitPhoneFilterChain extends RiskControlDecisionsFilterChain {
private Logger log = LoggerFactory.getLogger(RiskControlLimitPhoneFilterChain.class);
@Autowired
private RiskControlUsersService riskControlUsersService;
@Autowired
private OrderService orderService;
/**
* 标识===过滤器所属限制类型
* @return int
*/
@Override
protected int getThisRestrictiveType() {
return RiskControlRestrictiveEnum.LimitPhone.getCode();
}
/**
* 构造函数---注册到过滤器链
*/
public RiskControlLimitPhoneFilterChain() {
filterChains.add(this);
}
/**
* 风控决策引擎执行入口--限制手机号
*
* @param user, 用户ID
* @param manager 风控管理器
* @param restrictive 风控限制
* @author GuoTong
*/
@Override
public boolean execute(User user, RiskControlManager manager, RiskControlRestrictive restrictive) {
boolean restrictiveFlag = false;
try {
restrictiveFlag = super.executeDefaultHandler(user, manager, restrictive,this);
} catch (Exception e) {
log.error("RiskControlLimitAccountFilterChain execute error:", e);
}
return restrictiveFlag;
}
@Override
protected int countRiskControlLimit(String startTime, String endTime, User user) {
String mobile = user.getMobile();
if (StringUtils.isBlank(mobile)) {
return 0;
}
return orderService.countRiskControlPhoneLimit(startTime, endTime, mobile);
}
/**
* 保存用户--进入限制桶
* 子类必须重写
* @param riskControlUsers riskControlUsers
*/
protected void saveLimitUser(RiskControlUsers riskControlUsers) {
riskControlUsersService.save(riskControlUsers);
}
@Override
protected ReleaseTimeSetting getReleaseTimeSetting() {
return riskControlUsersService.selectReleaseTimeData();
}
}
SpringBoot+使用过滤器链执行风控决策的更多相关文章
- Go Revel - Filters(过滤器链)
`Fitlers`过滤器链是一个中间件,它们具有单独的功能,并作为管道对请求做链式处理.过滤器链执行框架的所有功能. 对过滤器链的源码分析,请移步 Go Revel - Filter(过滤器)源码分析 ...
- SpringBoot自定义过滤器的两种方式及过滤器执行顺序
第一种 @WebFilter + @ServletComponentScan 注解 1.首先自定义过滤器 如下自定义过滤器 ReqResFilter 必须实现 javax.servlet.Filte ...
- Spring Security(2):过滤器链(filter chain)的介绍
上一节中,主要讲了Spring Security认证和授权的核心组件及核心方法.但是,什么时候调用这些方法呢?答案就是Filter和AOP.Spring Security在我们进行用户认证以及授予权限 ...
- 【springboot】过滤器、监听器、拦截器,Aspect切片
转自: https://blog.csdn.net/cp026la/article/details/86501019 简介: 本章介绍拦截器.过滤器.切片对请求拦截的使用与区别,以及监听器在 spri ...
- SpringBoot学习(八)-->SpringBoot之过滤器、监听器
本文将直接使用@WebFilter和@WebListener的方式,完成一个Filter 和一个 Listener. 过滤器(Filter)和 监听器(Listener)的注册方法和 Servlet ...
- springboot 增加过滤器方法
在访问服务器时,我们需要控制用户是否允许权限,这个时候可以使用过滤器. 在springboot 配置过滤器的方法如下: 编写过滤器代码: package com.neo.filter; import ...
- spring boot 自定义过滤器链
spring boot 会按照order值的大小,从大到小的顺序来依次过滤. 贴下代码: package com.osp.ucenter; import org.springframework.boo ...
- 过滤器链chain.doFilter(request,response)含义
过滤器的生命周期一般都要经过下面三个阶段: 初始化 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Config 对象的引用. 过滤 过滤器的大多 ...
- springboot jsp,过滤器,拦截器
springboot使用jsp,过滤器,拦截器(拦截器与过滤器区别重点) jsp使用配置 一 创建springboot项目在maven中暂时只添加两个Dependencies :devtools(热部 ...
- SpringBoot图文教程6—SpringBoot中过滤器的使用
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文系列教程技术大纲 鹿老师的Java笔记 SpringBo ...
随机推荐
- MySQL数据库驱动mysql-connector-java与数据库版本的匹配
jar包的下载地址:https://dev.mysql.com/downloads/file/?id=477058 之前我的MySQL数据库驱动mysql-connector-java版本号为5.1. ...
- 概率论与数理统计教程(第二版,茆诗松,2010)PDF下载
概率论与数理统计教程(第二版,茆诗松,2010)PDF下载:共享地址
- 基于源码分析 SHOW GLOBAL STATUS 的实现原理
问题 在 MySQL 中,查询全局状态变量的方式一般有两种:SHOW GLOBAL STATUS和performance_schema.global_status. 但不知道大家注意到没有,perfo ...
- 使用Emgu.CV开发视频播放器简述
OpenCV是大名鼎鼎的视觉处理库,其对应的c#版本为Emgu.CV.本人采用Emgu.CV开发了一款视频播放软件,可对本地视频文件和rstp在线视频流播放,还具有对视频局部区域放大功能.虽然功能比较 ...
- sqlserver空间数据 + c# 实现查询附近的设备
前言 一个小需求的实现,做一个备忘,个人理解,可能存在错误. 客户有很多设备,这些设备分散在不同的地方,现在需要通过小程序获取附近的(比如1000米)之类的设备列表,以距离排序 第一个想到的的是找百度 ...
- 网站架构核心技disruptor
一 序:本章业务场景:队列在数据结构中是一种线性表,从一端插入数据,然后从另一端删除数据.作者举例的场景有:进行异步处理.系统解耦.数据同步.流量削峰.缓冲.限流等. 前面的比较浅,总结起来,核心知识 ...
- biancheng-Spring Cloud Alibaba Sentinel
http://c.biancheng.net/springcloud/sentinel.html Sentinel 是由阿里巴巴中间件团队开发的开源项目,是一种面向分布式微服务架构的轻量级高可用流量控 ...
- 文章学习|开放,让5G网络更智能
学习文章:开放,让5G网络更智能 介绍 从2G到5G,网络在不断发展,通信行业的生态系统在不断演进,运营商的角色也发生着改变. 在2G和3G时代,运营商作为服务提供商为用户提供通信业务和互联网业务,获 ...
- 反射:获取Class 类的实例(四种方法)
Class 类 对象照镜子后可以得到的信息:某个类的属性.方法和构造器.某个类到底实现了哪些接口.对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象.一个 Class 对象包含了 ...
- Apache Camel系列(2)----Hello World
下面创建一个Apache Camel的Hello World程序,该程序使用Maven,Intellij 15,运行环境是JDK 8. 1,创建一个maven工程,在pom.xml文件中添加apa ...