风控接入
本章指导将风控服务部署并接入 EasyFly-Ads 平台,包括服务部署、SDK 集成、规则配置和效果验证。
风控服务部署
Docker Compose 部署
在 docker-compose.yml 中添加风控服务:
yaml
risk-service:
image: easyfly/risk-service:latest
restart: always
ports:
- "8085:8080"
environment:
- DB_HOST=mysql
- DB_PORT=3306
- DB_USER=easyfly
- DB_PASSWORD=your_password
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=your_redis_password
- ES_HOST=elasticsearch:9200
volumes:
- ./logs/risk:/app/logs
- ./rules:/app/rules
depends_on:
- mysql
- redis
- elasticsearch环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
DB_HOST | MySQL 地址 | 127.0.0.1 |
DB_PORT | MySQL 端口 | 3306 |
REDIS_HOST | Redis 地址 | 127.0.0.1 |
ES_HOST | Elasticsearch 地址 | 127.0.0.1:9200 |
RISK_SCORE_THRESHOLD | 风险评分阈值 | 60 |
RULE_REFRESH_INTERVAL | 规则刷新间隔(秒) | 300 |
SDK 集成
Android SDK
kotlin
// 初始化风控SDK
RiskSDK.init(context, RiskConfig.builder()
.setAppId("your_app_id")
.setServerUrl("https://api.yourdomain.com/risk")
.setDeviceFingerprint(true) // 开启设备指纹采集
.setDebugMode(BuildConfig.DEBUG)
.build())
// 上报用户行为
RiskSDK.reportEvent(RiskEvent.builder()
.setEventType("AD_WATCH")
.setUserId(userId)
.setTimestamp(System.currentTimeMillis())
.addExtra("ad_id", adId)
.addExtra("duration", watchDuration)
.build())iOS SDK
swift
// 初始化
let config = RiskConfig(
appId: "your_app_id",
serverUrl: "https://api.yourdomain.com/risk",
deviceFingerprint: true,
debugMode: false
)
RiskSDK.initialize(config)
// 上报行为
let event = RiskEvent(
eventType: .adWatch,
userId: userId,
extra: ["ad_id": adId, "duration": duration]
)
RiskSDK.reportEvent(event)后端 API 接入
java
// 风控检查
@PostMapping("/risk/check")
public RiskResult checkRisk(@RequestBody RiskRequest request) {
// 调用风控服务
return riskService.evaluate(request);
}
// 使用示例
RiskRequest request = RiskRequest.builder()
.userId("123456")
.eventType("WITHDRAWAL")
.amount(100.00)
.deviceId("device_fingerprint_xxx")
.ipAddress("1.2.3.4")
.build();
RiskResult result = riskService.evaluate(request);
if (result.getRiskScore() > 60) {
// 触发风控拦截
throw new RiskException("该操作存在风险,已限制");
}规则配置
规则文件结构
规则文件放在 ./rules/ 目录下,使用 JSON 格式:
json
{
"ruleId": "R001",
"name": "批量注册检测",
"description": "检测短时间同设备大量注册",
"enabled": true,
"priority": 1,
"conditions": [
{
"field": "device_register_count",
"operator": "GREATER_THAN",
"value": 5,
"timeWindow": "1h"
},
{
"field": "register_interval",
"operator": "LESS_THAN",
"value": 10,
"unit": "minutes"
}
],
"action": {
"type": "INCREASE_SCORE",
"score": 40,
"tag": "batch_register"
}
}预置规则
| 规则ID | 规则名称 | 风险场景 |
|---|---|---|
| R001 | 批量注册检测 | 同设备短时间多账号 |
| R002 | 模拟器检测 | 在模拟器中运行 |
| R003 | VPN/代理检测 | 使用VPN或代理IP |
| R004 | 广告观看异常 | 观看时长/频次异常 |
| R005 | 提现异常检测 | 短时间多笔提现 |
| R006 | 邀请关系异常 | 循环邀请/虚假邀请 |
| R007 | 设备信息篡改 | 设备ID被修改 |
风控响应策略
在 API 网关层统一处理风控结果:
java
// 拦截器
@Component
public class RiskInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
RiskResult result = riskService.evaluate(request);
if (result.getRiskScore() >= 80) {
// 高风险 - 直接拒绝
response.setStatus(403);
response.getWriter().write("{\"code\":403,\"msg\":\"操作被风控拦截\"}");
return false;
}
if (result.getRiskScore() >= 60) {
// 中风险 - 标记并限制
request.setAttribute("risk_level", "MEDIUM");
request.setAttribute("risk_tags", result.getTags());
}
return true;
}
}验证与测试
模拟风控触发
使用测试工具模拟异常行为:
bash
# 模拟批量注册
for i in {1..10}; do
curl -X POST https://api.yourdomain.com/register \
-H "Content-Type: application/json" \
-d "{\"device_id\":\"test_device_001\",\"phone\":\"1380013800$i\"}"
done
# 查看风控日志
curl https://api.yourdomain.com/risk/logs?device_id=test_device_001检查清单
- [ ] 风控服务启动正常,健康检查通过
- [ ] SDK 初始化成功,设备指纹正常采集
- [ ] 正常用户行为未被误拦
- [ ] 模拟作弊行为被正确识别
- [ ] 风险评分和标签准确
- [ ] 风控日志正常记录
- [ ] 黑白名单功能正常
- [ ] 规则动态刷新生效
监控告警
建议配置以下监控指标:
| 指标 | 告警阈值 |
|---|---|
| 风控拦截率 | > 10% 需关注 |
| 服务响应时间 | > 500ms |
| 规则命中率 | 突增 50% 告警 |
| 服务可用性 | < 99.9% |