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 ...
随机推荐
- Vue3项目运行时报错误:TypeError Cannot read properties of undefined (reading 'filter')
let matched = this.$route.mached.filter(item => item.name);方法报错:TypeError Cannot read properties ...
- Python PEP8 代码规范常见问题及解决方法
之前一直用 Python IDLE 写代码,最近换成 PyCharm 写代码总是会出现波浪号,这才了解到 Python 的 PEP8 代码规范,所以将常见的 PEP8 代码规范问题和解决方法记录一下, ...
- 使用 httputils + sbe (Simple Binary Encoding) 实现金融级 java rpc
1.认识 Simple Binary Encoding (sbe) 高性能Java库 Agrona 的主要目标是减少性能瓶颈,通过提供线程安全的直接和原子缓冲区.无装箱操作的原始类型列表.开散列映射和 ...
- VSTO踩坑记录(3)- 用ClickOnce发布outlook插件 - 我数据文件呢?
概述 上面两篇文章虽然很简略,不过vsto说白了就是winform开发,所以需要说的内容不是很多,下面直接到发布阶段. 这次先介绍ClickOnce的发布方式,默认右击项目 - 发布,就是这种方式. ...
- [LC515]在每个树的行中找最大值
题目内容 题目分析 这是一道典型的树结构遍历题,可以使用层序遍历(BFS)或者(DFS)进行解题. 在BFS中,使用队列结构遍历树的每一层并维护每层的最大值. 在DFS中,由于并不是一层一层的去访问树 ...
- 异步 QQ 机器人框架_NoneBot
一.NoneBot使用 1) #监控发送的消息"群发"的事件@on_command('send_msg', aliases=('群发',))async def send_msg(s ...
- 使用CRM REST Builder的Predefined Query在js结合FetchXML语句进行查询
一般情况下使用拓展工具RESTBuilder编辑器,可以很方便的进行操作js中增删改查均能实现,但在某些较为特殊的场景下,需要根据条件去拼接查询过滤条件的,使用编辑器生成的代码无法实现,需要结合使用f ...
- Solution Set -「OurOJ Contest #2587」浅写
\(\mathscr A\sim\)「OurOJ #47030」_ Link & Submission & Tags:「A.DP-计数 DP」「A.数学-Stirling 数/反演 ...
- 服务器主机:复杂理论的视角与SEO策略
本文分享自天翼云开发者社区<服务器主机:复杂理论的视角与SEO策略>,作者:不知不觉 在数字世界的演变中,服务器主机在信息存储和数据处理方面发挥着核心作用.本文将带你重新认识服务器主机的价 ...
- 初探ASP.NET Core 3.x (2) - ASP.NET Core与ASP.NET前世今生
本文地址:https://www.cnblogs.com/oberon-zjt0806/p/12210662.html 注意 本节是历史课,且绝大多数内容来自于百科或者其他的什么资料来源,如果不感兴趣 ...