虎符 业务安全网关-WEB端接口加签 服务接入说明
一、简介
欢迎使用京东业务安全-接口验签服务。
随着互联网的迅速发展,针对APP及WEB端的恶意流量攻击层出不穷,不断危害着企业业务的安全运转。例如:大量的渠道假量消耗了企业的投放费用,企业意识到流量质量时,已经浪费了巨量投放资金;营销资源被恶意流量占领,使企业业务方的营销资源不能足够的传达到价值用户;在注册、登录、领券、评论等各个业务环节,恶意流量会对企业正常业务氛围进行破坏;企业业务特点的传达、业务氛围等各方面的影响会导致正常用户的流失影响业务的整个商业优势。恶意流量对业务造成的影响主要可以归纳为如下几类:
(1)“易攻击”:业务方均存在着机器流量攻击,高价值业务接口被刷,对于攻击者的攻击和破解行为无感知。除去服务端的对抗策略外,客户端破解成本过低也是导致自动化作弊工具产生的原因。
(2)“易破解”:客户端逻辑被逆向过于容易,接口盗用、非法接口调用等情况泛滥,甚至导致关键字段采集不到,给业务团队带来巨大的资损。
(3)“服务器压力激增”:客户端接口防护链路不完整,抬高服务稳定性资源消耗。业务未接入接口验签,导致业务接口安全防护失衡,大部分机器流量的压力在业务集群积压。
京东结合自身多年的业务安全经验及海量数据的沉淀,形成了接口验签的解决方案,旨在增强APP及WEB端接口数据保护能力,对抗黑产批量访问敏感接口。提高黑产攻击的门槛,最大限度地提升黑产获利的成本。
(1)提供APP 及WEB端的 接口保护能力。识别虚假流量,节省大量营销资源。
(2)增强 SDK 二进制对抗能力。提升接口攻击和破解的成本,在接口层面增加验签协议设计,客户端增强二进制防护对抗技术强度。
(3)为引擎侧数据赋能。用客户端上报的数据建立端与云的预警与防护,对于攻击者的攻击和破解为进感知与防御。
(4)操作轻快适用。黑产依据业务制定攻击策略,防御也需按照业务形态而变。业务方依据自身业务需求,可以选择定制最切合自身系统需要的验签方式。
二、通讯流程
三、接入步骤
3.1 虎符官方赋能场景接入说明
京东业务安全-接口验签服务做为云鼎的一个能力业务组件,客户需要接入虎符进行访问。虎符场景接入说明,请参考 https://yd-doc.jdcloud.com/docs/5-hufu/5-2-guanfang/apply.html
请联系云鼎运营申请加签 appId
3.2 客户前端 集成接口验签SDK
步骤一、客户前端集成接口验签SDK,目前支持CDN方式导入,示例如下
<script src="https://storage.360buyimg.com/webcontainer/js_security_v4.js"></script>
步骤二、客户每个前端页面,在created生命周期中实例化ParamsSign对象,并保存在全局pSign变量中,具体参数请参考4.1.1
created() {//在created生命周期中实例化对象(必须)
this.PSign= new ParamsSign({
appId: "xxxxxxx",//验签ID,请联系云鼎运营申请加签 appId
debug: true, //测试时开启调试,切记:上线后设置为false。
preRequest:false,
onSign: ({ code }) => { // 签名可用率监控,业务方自行上报
0: 成功
1: 参数错误
2: 缺少验签ID
3: 获取token失败
4: 签名失败
-1: 其他错误
},
onRequestTokenRemotely: ({ code, message }) => { //算法接口可用率监控,业务方自行上报
200: 请求成功,表示动态算法接口请求成功,获取到动态token
其他: 请求失败
},
onRequestToken: ({ code, message }) => { //token的可用率监控,业务方自行上报
0: 动态token
1: 本地token
}
});
},
步骤三、利用业务字段构造加签参数,并调用全局pSign变量的sign()方法进行加签,sign()方法请求参数请参考4.1.2,返回参数请参考4.1.3。用于加签参数构造的业务字段无特殊要求,由应用方根据业务情况自主选择
步骤四、将sign()方法返回的h5st、_stk字段透传到客户服务端。
//业务请求参数
const params = {
key1: "value1",
key2: "value2",
key3: "value3"//请注意这个字段不是加签参数
};
//构造加签参数
const paramsSign = {};
paramsSign['key1'] = params['key1']
paramsSign['key2'] = params['key2']
//调用加签函数
this.PSign.sign(paramsSign).then(signedParams => {
params.h5st = signedParams.h5st; //h5st字段为base64编码,可能包含特殊字符,get请求需要urlencode。
params._stk = signedParams._stk; //签名使用参数key列表
//业务请求
this.request('get', 'https://www.xxxxxxxx.com/test', params) //调用客户服务端,透传h5st、_stk字段
});
注意事项:
- 点击触发加固的按钮需要做防抖处理,防止多次加固。
- 不可为了方便在统一请求工具函数中直接接入。
- 接口加固不可全部接口都加固,只针对有利益点的,容易被黑产利用的接口进行验签。
3.3 客户服务端调用验签服务进行风险判定
由业务后端请求风险判定服务,对业务请求进行验签,判定服务会在返回判定结果。如果有请求被判定为风险,前端请求会收到业务后端返回的异常状态码,前端需要根据状态码展示兜底页面,比如:奖品抢完了,下次再来等。判定服务的具体调用过程详见后端调用文档,可以参考4.2,也可以从如下位置获取
3.3 客户服务端调用验签服务进行风险判定
由业务后端请求风险判定服务,对业务请求进行验签,判定服务会在返回判定结果。如果有请求被判定为风险,前端请求会收到业务后端返回的异常状态码,前端需要根据状态码展示兜底页面,比如:奖品抢完了,下次再来等。判定服务的具体调用过程详见后端调用文档,可以参考4.2,也可以从如下位置获取
四、API参考
4.1 接口加签(前端集成)
4.1.1 ParamsSign对象参数列表
序号 | 字段 | 类型 | 是否必须 | 备注 |
---|---|---|---|---|
1 | appId | string | 是 | 验签ID,请联系云鼎运营申请加签 appId |
2 | preRequest | boolean | 否 | 用于配置提前请求动态算法和token默认值:true |
3 | debug | boolean | 否 | 开启debug模式,输出log信息,上线前切记关闭debug模式默认值:false |
4 | onSign | 签名监控回调事件 | 是 | 业务每次调用验签时会触发,用于前端业务监控组件加密签名可用率onSign({ code, message,data }) // 可用率监控code: 0: 成功 1: 参数错误 2: 缺少appId 3: 获取token失败 4: 签名失败 -1: 其他错误 |
5 | onRequestTokenRemotely | 算法请求监控回调事件 | 是 | 业务初始化时触发,动态算法接口请求可用率,用于前端业务监控组件获取动态算法的可用率onRequestTokenRemotely ({ code, message }) // 可用率监控code:200 - 请求成功,表示动态算法接口请求成功,获取到动态token其他为失败 |
6 | onRequestToken | token监控回调事件 | 否 | 业务初始化时触发,标记当前验签的形式,用于前端业务监控组件备灾策略执行的比例onRequestToken({ code, message }) // 业务监控code: 0: 动态token 1:本地token |
4.1.2 加签请求参数
序号 | 字段 | 类型 | 是否必须 | 备注 |
---|---|---|---|---|
1 | 业务入参 |
object | 是 | 入参只接收:String,Boolean,Number 三种类型, 如有Object类型参数例如Json,需要序列化成字符串后再传入。加签参数不做具体要求,选择加签参数标准是 重要的必传的业务参数 (重要)。示例如下:{``key1:'login',//业务重要参数 key2: 'appId_1',//业务重要参数} |
4.1.3 加签返回参数
序号 | 字段 | 类型 | 是否必须 | 备注 |
---|---|---|---|---|
1 | 业务入参 |
object | 是 | { // 返回的业务参数``key1:'login',//业务重要参数 key2: 'appId_1',//业务重要参数h5st:'xx', // 签名相关参数_stk:'key1,key2', // 签名使用业务参数key列表,请使用小写逗号(,)进行拼接_ste:1, // 1 H5渠道,2小程序渠道,业务不需要关心} |
4.1.4 代码示例
①请求流要实时加签不要缓存验签字段(h5st),并且要前端防抖,防止一个请求多次执行加签操作。
②每个页面,一个appId,new ParamsSign只实例化一次,并保存在全局pSign变量中。不可多次实例化
③加签参数只接收:String,Boolean,Number 三种类型,如有Object类型参数(如Json),需要业务手动序列化为字符串后传入。要保证加签参数和业务接口请求时的参数完全一致。
④选择加签参数标准是 重要的必传的业务参数。
<template>
<div>
<div @click="clickBtn()">加固</div>
</div>
</template>
<script>
export default {
data() {
return {
PSign: "",
};
},
created() {//在created生命周期中实例化对象(必须)
this.PSign= new ParamsSign({
appId: "b628c",//验签ID,请联系云鼎运营申请加签 appId
debug: true, //测试时开启调试,切记:上线后设置为false。
preRequest:false,
onSign: ({ code }) => { // 签名可用率监控,业务方自行上报
0: 成功
1: 参数错误
2: 缺少验签ID
3: 获取token失败
4: 签名失败
-1: 其他错误
},
onRequestTokenRemotely: ({ code, message }) => { //算法接口可用率监控,业务方自行上报
200: 请求成功,表示动态算法接口请求成功,获取到动态token
其他: 请求失败
},
onRequestToken: ({ code, message }) => { //token的可用率监控,业务方自行上报
0: 动态token
1:本地token
}
});
},
methods: {
clickBtn() {//重要:按钮要做快速点击防抖,防止连续多次执行加固操作
//业务请求参数
const params = {
key1: "value1",
key2: "value2",
key3: "value3"//请注意这个字段不是加签参数
};
//构造加签参数
const paramsSign = {};
paramsSign['key1'] = params['key1']
paramsSign['key2'] = params['key2']
//调用加签函数
this.PSign.sign(paramsSign).then(signedParams => {
params.h5st = signedParams.h5st; //h5st字段为base64编码,可能包含特殊字符,get请求需要urlencode。
params._stk = signedParams._stk; //签名使用参数key列表
//业务请求
this.request('get', 'https://www.xxxxxxxx.com/test', params)
});
}
};
</script>
4.2 接口验签(外部用户调用云鼎)
4.2.1 调用方式
- 应用方调用云鼎对外接口请参考: https://yd-doc.jdcloud.com/docs/5-hufu/5-2-guanfang/apply.html
- 调用代码示例详情见云鼎对外接口文档 2.3部分
4.2.2 请求参数
4.2.2.1 请求一级参数
名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
requestId | String | True | 由网关为每次请求生成唯一ID |
ip | String | True | 客户端公网出口IP |
pin | String | True | 用户pin |
agent | String | True | User-Agent |
host | String | True | 客户端host |
path | String | True | 用户当前请求的完整URI,参数也需要带上 |
isBlock | String | False | 当前请求是否开启拦截,0:关;1开;格式:{"组件id":"开关"}本次如果WAAP认为有风险,在网关侧本次请求是否会拦截的标识例如:如果WAAP返回有风险,并且网关会拦截,则传递{"组件id":"1"}即可如果业务网关不会拦截则传递{"组件id":"0"}即可 |
forcebot | String | False | 压测标识,0:关;1:开;默认值为0; |
gwProxyParams | Map | True | MAP类型,具体key请参考所有”二级参数 gwProxyParams“ |
headers | Map | False | MAP类型,具体key请参考所有”二级参数 headers“ |
4.2.2.2 请求二级参数 gwProxyParams
名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
appid | String | True | 用唯一标识,请使用“用户京东云pin+下划线+用户自身应用唯一标识“,防止应用id重复导致的计算错误 |
functionId | String | True | 接口标识 |
h5st | String | True | 在业务请求中追加的安全字段 |
signedParams | Map |
False | 获取_stk参数,该参数为前端用了哪些字段做签名,网关需解析该字段,并使用逗号分割,将所有参数以及值放入该MAP" |
4.2.2.3 请求二级参数 header
名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
X-Requested-With | String | False | 请求类型 |
Origin | String | False | Origin |
Accept-Encoding | String | False | 接受编码 |
Content-Type | String | False | 内容类型 |
X-Forwarded-For | String | False | 请求源IP链 |
Request-Method | String | False | 请求Method |
4.2.3返回参数
名称 | 类型 | 描述 |
---|---|---|
code | Integer | 返回码,0表示成功(无错误),详见4.2.3.1 |
level | Integer | 风险等级,0:无风险;1-5:风险等级由低到高,详见4.2.3.2 |
riskType | Set\ |
风险组件识别的风险类型 |
extras | Map |
风险组件输出的额外信息,无特殊情况一般为空 |
message | String | 风险组件输出的消息 |
4.2.3.1返回码定义
code | message | 说明 |
---|---|---|
0 | success | 成功 |
101 | apig_id_rejected | 当前网关ID被拒绝访问 |
200 | empty_param | 参数为空 |
201 | param_missing | 参数缺失 |
202 | illegal_param | 存在非法参数 |
301 | inner_error | 内部错误 |
302 | timeout | 调用超时 |
303 | component_error | 组件调用错误 |
4.2.3.2 风险等级定义
level | 说明 |
---|---|
0 | 无风险 |
1 | 低风险 |
2 | 中低风险 |
3 | 中风险 |
4 | 中高风险 |
5 | 高风险 |