适用版本: - Android-SDK 5.5.1-5.8.0(不包含 5.8.0),例如 5.7.9.3 - Android-SDK 5.8.0 开始以及以后,带 -pro 的版本,例如5.8.0-pro 之前版本文档参考Android-C#接入教程(5.4.6以及更低版本) (https://support.dun.163.com/documents/761315885761396736?docId=896491640008171520)。 ## 隐私说明 请参照网易易盾隐私政策 (https://dun.163.com/clause/privacy),请将易盾隐私政策链接放到应用“用户协议”中。 ## 更新说明 注:从5.4.6及更低版本升级到5.5.1以及更高版本需注意 1.init接口的回调 在5.4.6以及更早版本,回调的定义如下: Code (C#): public class HTPCallback : AndroidJavaProxy { public HTPCallback() : base("com.netease.htprotect.callback.HTPCallback") { } public virtual void onReceive(int code, string msg) { } } 实现示例如下: Code (C#): class MyHtpCallback : NetEase.HTPCallback { public override void onReceive(int code, string msg) { Debug.Log("Call InitCallBack"); Debug.Log("code = " + code + " msg = " + msg); } } 在5.5.1以及更高版本中,回调的定义改为如下: Code (C#): public interface HTPCallback { void onReceive(int code, string msg); } 实现示例如下: Code (C#): class MyHtpCallback : NetEase.HTPCallback { public void onReceive(int code, string msg) { Debug.Log("Call InitCallBack"); Debug.Log("code = " + code + " msg = " + msg); } } 区别:回调类型发生变化,不再需要override关键字。 2.getTokenAsync异步接口的回调 在5.4.6以及更早版本,回调的定义如下: Code (C#): public class GetTokenCallback : AndroidJavaProxy { public GetTokenCallback() : base("com.netease.htprotect.callback.GetTokenCallback") { } public virtual void onResult(AndroidJavaObject javaResult){} } 实现示例如下: Code (C#): class MyGetToken : NetEase.GetTokenCallback { public override void onResult(AndroidJavaObject javaResult) { int code = javaResult.Get("code"); Debug.Log("token code:" + code); if (code == NetEase.AntiCheatResult.OK) { string token = javaResult.Get("token"); Debug.Log("token:" + token); } else { // 请根据错误码,检测相关代码 } } } 在5.5.1以及更高版本中,回调的定义改为如下: Code (C#): public interface GetTokenCallback { void onResult(AntiCheatResult antiCheatResult); } 实现示例如下: Code: class MyGetToken : NetEase.GetTokenCallback { public void onResult(NetEase.AntiCheatResult antiCheatResult) { if (antiCheatResult.code == NetEase.AntiCheatResult.OK) { string token = antiCheatResult.token; Debug.Log("token:" + token); } else { // 请根据错误码,检测相关代码 } } } 区别:回调类型发生变化,不再需要override关键字;onResult的参数发生变化,现在参数是AntiCheatResult类型 ## 接入说明 接入“智能风控” SDK,开发者需要完成以下步骤: Code: 1. 根据应用/游戏开发平台,将对应sdk c#文件夹内的.aar和.cs文件导入到工程目录,并修改项目配置; 2. 接入风控SDK必接接口,根据业务需求接入建议接口; 3. 测试风控SDK接入是否正确; 4. 验证风控SDK功能效果; 5. 按业务常规发版流程进行测试与发版 游戏必须接入: - 全局必须要接入的接口:初始化接口 (#4.1) - 游戏类型应用反外挂场景业务必须要接入的接口:设置用户信息接口 (#4.2) - 选择角色进入游戏后,接入该接口完成数据透传:同步获取凭证 (#4.4)/异步获取凭证 (#4.5) 建议接入: - 获取风控基础信息:交互接口 (#4.8) - 协议保护/防脱机:安全通信协议接口 (#4.11) ## 接入步骤 SDK 涉及到以下文件: 请登录易盾官网后台 (https://dun.163.com/dashboard?v=0116&locale=zh-CN#/m/risk-manage/service/)风控引擎-服务管理获取SDK,详情如图。image title (https://nos.netease.com/yidun/e5adb07ec735e95205e83d48bb2a00aa.png) Code: HTProtectLib-X.X.X.X.aar NetSecProtect.cs 注意: 打包出来的 apk,必须包含 lib/xxx/libNetHTProtect.so 与 assets/motion/ 下的所有so文件。 ### 导入SDK 将提供的aar和cs文件拷贝到工程里,建议放在**Assets/Plugins/Android/**这个目录下。 aar的操作可以参考官网说明文档https://docs.unity3d.com/cn/2019.4/Manual/AndroidAARPlugins.html ### 过滤需要的 ABI SDK 提供了 armeabi、armeabi-v7a、x86、arm64-v8a、x86_64五种 的支持,默认会导出这五种 ABI。 注意: - 如果应用/游戏本身不支持这么多 ABI,就需要对最终导出的 ABI 进行过滤,不然会 crash; - 如果 APP 只需要支持特定的 ABI,比如 armeabi,armeabi-v7a、x86 三种,可以在 build.gradle 添加如下配置: Code (java): defaultConfig { applicationId "com.XX.XXX" minSdkVersion XX targetSdkVersion XX versionCode XX versionName "X.X.X" ndk { abiFilters "armeabi", "armeabi-v7a", "x86" } } ### 添加权限信息 SDK 不会申请任何权限,但是为了提升风控的效果,建议在 AndroidManifest.xml 文件中添加下列权限配置: Code (java): ### 添加 ProGuard 配置 若使用 ProGuard 进行混淆,需要将 SDK 使用的类排除掉。若使用 Android Studio 开发,则在 proguard-rules.pro 文件中添加如下信息: Code (java): -keep class com.netease.htprotect.**{*;} -keep class com.netease.mobsec.**{*;} ## SDK 接入调用说明 重要:如果是在子线程调用智能风控的接口,请务必在子线程开始处调用 AndroidJNI.AttachCurrentThread() ,并且在子线程结束前调用 AndroidJNI.DetachCurrentThread() ,否则会发生内存泄漏或崩溃。 部分产品相关参数请用账号登陆易盾官网控制台获取参考image title (https://nos.netease.com/yidun/e729ec778f5485d37473476c3e82f8a4.png) ### SDK 初始化接口(init) #### 接口用途: 用于初始化智能风控 SDK。 #### 接入须知: 1. 使用其他接口之前,必须先调用初始化接口(init),建议在应用/游戏启动过后第一时间调用(初始化后,并不会获取任何个人隐私相关信息); 2. 该接口为 必须调用接口。 #### 函数原型: Code (c#): public static void init(string productId, NetEase.HTPCallback cb, NetEase.HTProtectConfig hTProtectConfig) #### 参数说明: 参数 | 说明 | 必要性 productId | 易盾HTP分配的productId,可登录易盾后台获取 | 必填 cb | 初始化是否成功的回调类 | 可选,不需要可填null config | 配置类的对象 | 可选,不需要可填null #### 配置类HTProtectConfig设置: ##### (1) 设置服务器归属地 Code (c#): public void setServerType(int serverType) 智能风控默认上报的服务器为中国大陆的服务器,若需要更改服务器归属地,可以调用该接口进行配置,支持的类型如下: 参数 | 赋值 | 说明 serverType | 1 | 中国大陆地区,默认为该值,无须设置 serverType | 2 | 中国台湾地区 serverType | 3 | 海外地区 ##### (2) 设置渠道信息 Code (c#): public void setChannel(string channel) 若需要传递当前应用包体来源渠道可调用该接口(比如:应用宝渠道编号/信息)。 ##### (3) 设置额外数据 Code (c#): public void setExtraData(string key, string value) 若需要客户端传递额外信息给易盾,可调用该接口,支持多次调用,但必须在 init 之前设置。 ##### (4) 设置 gameKey Code (c#): public void setGameKey(string gameKey) 主要跟安全通信的接口相关联,用于游戏类型应用,非游戏类型应用或不需要可以忽略,可以自定义32位长度字符串。 gameKey主要用于以下接口: - 数据校验 - 存档加解密 ##### (5) 设置私有化地址 Code (c#): public void setHost(string host) 私有化的客户需要通过该接口设置服务器地址,其他客户可以忽略。 参数说明: - 配置域名的,只需填写域名即可,SDK会自动加上前缀“https://”,举例如下所示: Code (c#): config.setHost("xxxxx.xxxx.xxxx"); - 配置ip和端口的,举例如下所示: Code (c#): config.setHost("xx.xx.xx.xx:xxx"); #### 回调类NetEase.HTPCallback: 回调类的定义如下: Code (c#): public interface HTPCallback { void onReceive(int code, string msg); } 在调用初始化接口时,需新建一个类,继承NetEase.HTPCallback,并实现 onReceive 方法,比如 Code (c#): class MyHtpCallback : NetEase.HTPCallback { public void onReceive(int code, string msg) { Debug.Log("Call InitCallBack"); Debug.Log("code = " + code + " msg = " + msg); // 如果code == 200,说明反外挂一切正常 // 如果code == 400,请将 msg 发送到贵方服务端,由贵方服务端通过[getConfig接口](https://support.dun.163.com/documents/761315885761396736?docId=771983453572567040)转发给易盾服务端,由易盾服务端响应 // 易盾服务端返回结果,再将结果通过 通用查询接口(Cmd_SetConfigData) 反馈给反外挂sdk // NetSecProtect.ioctl(RequestCmdID.Cmd_SetConfigData, configData); // responseData为易盾服务端返回的数据 } } 注:SDK 会启动线程调用 HTPCallback 回调函数,请注意多线程问题,尤其是主线程。 #### 示例代码: Code (c#): using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; using System; using System.Text; using System.Threading; public class MainManager : MonoBehaviour { void Start () { #if UNITY_ANDROID /** * 初始化 * 必调接口 * 使用其他接口之前,必须先调用初始化接口,建议在游戏启动后第一时间调用。 */ // 初始化配置 NetEase.HTProtectConfig htpConfig = new NetEase.HTProtectConfig(); htpConfig.setServerType(1); // 服务器所在地址,1:中国大陆,2:中国台湾地区,3:其他地区,4:欧盟地区 htpConfig.setChannel("testchannel"); // 渠道 htpConfig.setExtraData("111", "2222"); // 额外信息,反作弊接口需要,可不设置 htpConfig.setExtraData("3333", "4444"); NetSecProtect.init("易盾提供的产品id", new MyHtpCallback(), htpConfig); // 启动防剥离线程,可选 Thread daemonThread = new Thread(() => { InitDaemonThread(); }); daemonThread.Start(); #endif } ### 设置用户信息接口(setRoleInfo) #### 接口用途: 游戏类型应用,在进行数据采集的过程中,会将角色 ID,角色名称、用户/角色账号等设置在风控 SDK 采集的数据中一同上传,用于表示角色信息,以便对有恶意、风险行为的用户/角色进行相应的处置。 #### 接口须知: 1. 须在 SDK 初始化 (#4.1)且 用户同意隐私政策后才能调用该接口; 2. 凡是涉及到用户登录、或者切换角色的地方,均需要调用该接口设置或者更新用户/玩家信息; #### 函数原型: Code (c#): public static int setRoleInfo(string businessId, string roleId, string roleName, string roleAccount, string roleServer, int serverId, string gameJson); #### 参数说明: 参数 | 说明 | 必要性 businessId | 当前业务 ID | 必填 roleId | 用户/玩家的角色 ID | 必填 roleName | 用户/玩家的角色名称 | 可选,不需要可填null roleAccount | 用户/玩家的账号 | 必填 roleServer | 用户/玩家的角色的服务器名称 | 可选,不需要可填null serverId | 用户/玩家的角色所属服务器的 ID | 可选,不需要请传入-1 gameJson | 游戏类型应用需要上传的信息,对应一个 json 字符串 | 可选,不需要可填null gameJson 字段说明: key 名称 | key 类型 | key 值 | 必要性 | 说明 游戏版本号 | String | GameVersion | 可选,不需要可填null | 游戏版本号 资源文件版本 | String | AssetVersion | 可选,不需要可填null | 游戏类型应用的资源文件版本号 #### 函数返回: 函数返回 int 类型,可能出现的值如下: 值 | 说明 0 | 成功 -201 | 未初始化 -203 | businessId 不合法 #### 示例代码: Code (java): NetSecProtect.setRoleInfo("易盾提供的业务id","123456","易小盾","yd@163.com", "游戏测试服", 123, ""); ### 登出接口(logOut) #### 接口用途: 为了更好的统计该用户/玩家角色在本次登录后的行为,精准标识和打击有恶意行为的用户/玩家。 #### 接入须知: 1. 须在 设置用户信息接口 (#4.2)接口被调用后方可调用,在用户/玩家退出当前角色(包括切换角色)或者退出游戏时调用接口。 2. 此接口主要用于判断用户/玩家本次生命周期,不强制要求接入。 3. 如果未调用初始化,此接口默认为空,不会执行任何逻辑。 #### 函数原型: Code (c#): public static void logOut(); #### 示例代码: Code (c#): NetSecProtect.logOut(); ### 同步获取凭证(getToken) #### 接口用途: 用于关键业务节点风险防控场景中,比如注册、登录、领券、抽卡、兑换、点赞、评论等业务场景。业务方可通过此接口,获取检测唯一凭证 token。业务服务端通过此凭证实时获取当前用户/玩家风险检测结果,并根据结果进行处置。 Code (java): 接口适用场景为: 1、游戏类应用,当 SDK 数据上报接口被屏蔽导致数据上报失败时,通过 getToken 接口获取 SDK 采集信息,并由客户服务端传递给易盾服务器; 2、全类型应用,在关键业务节点主动调用检测时,通过 getToken 接口获取检测凭证,由客户服务端通过 token 凭证从易盾服务器查询检测结果。 #### 接入须知: 1. 须在 SDK 初始化 (#4.1)且用户同意隐私政策后才能调用该接口,网易易盾隐私说明 (https://dun.163.com/clause/privacy)。 2. 内部存在网络请求,只允许在子线程上调用。 3. 返回值AntiCheatResult中token的使用方法请参考“后端接入-智能风控数据服务接口-在线检测接口 (https://support.dun.163.com/documents/761315885761396736?docId=834511620372037632)”。 #### 函数原型: Code (c#): public static NetEase.AntiCheatResult getToken(int timeout, string businessId) #### 参数说明: 参数 | 说明 | 必要性 timeout | 函数超时时间 | 必填,单位毫秒,[100,10000],此区间外的默认为3000 businessId | 业务 ID | 必填,由易盾后台分配,并在官网“服务管理”中查询 #### 返回值: NetEase.AntiCheatResult类说明 Code (c#): public class AntiCheatResult { public int code; public string codeStr; public string token; public String businessId; } 变量说明: 变量 | 说明 code | 结果码,不同结果码含义如下:200:表示调用成功,其他结果码均表示调用失败;-201:SDK未初始化;-202:在主线程运行;-203:businessId不合法;-204:其他情况 codeStr | 结果码对应的字符说明,200:success,-201:error not init,-202:error. run on main thread,-203:businessId invalid,-204:gen token error token | 当 code 为200时,返回正常token。当网络状态不佳或者超时时,会返回离线 token(8KB左右) businessId | 用于透传上报给反垃圾系统,实现数据互通,提升检测效果(如未接入反垃圾系统,可以不用处理此参数) #### 示例代码: Code (c#): // 同步获取反作弊token线程 public void GetTokenThread() { AndroidJNI.AttachCurrentThread(); NetEase.AntiCheatResult acResult = NetSecProtect.getToken(3000, "易盾提供的业务id"); Debug.Log("token code:" + acResult.code); Debug.Log("token:" + acResult.token); AndroidJNI.DetachCurrentThread(); } // 同步接口,必须在子线程中调用 Thread tokenThread = new Thread(() => { GetTokenThread(); }); ### 异步获取凭证(getTokenAsync) #### 接口用途: 同 同步获取凭证 (#4.4)。 #### 接入须知: 1. 须在 SDK 初始化 (#4.1)且用户同意隐私政策后才能调用该接口,网易易盾隐私说明 (https://dun.163.com/clause/privacy)。 2. 如果未调用初始化,此接口默认为空,不会执行任何逻辑。 3. 返回值AntiCheatResult中token的使用方法请参考“后端接入-智能风控数据服务接口-在线检测接口 (https://support.dun.163.com/documents/761315885761396736?docId=834511620372037632)”。 #### 函数原型: Code (c#): public static void getTokenAsync(int timeout, string businessId, NetEase.GetTokenCallback callback) #### 参数说明: 参数 | 说明 | 必要性 timeout | 函数超时时间 | 必填,单位毫秒,[100,10000],此区间外的默认为3000 businessId | 业务 ID | 必填,由易盾后台分配,并在官网“服务管理”中查询 callback | token 的回调 | 必填,用来接收 token #### 返回值: NetEase.GetTokenCallback说明: Code (c#): // token接口类 public interface GetTokenCallback { void onResult(AntiCheatResult antiCheatResult); } 需新建类,继承 NetEase.GetTokenCallback, 并实现 onResult 方法,比如 Code (c#): class MyGetToken : NetEase.GetTokenCallback { public void onResult(NetEase.AntiCheatResult antiCheatResult) { if (antiCheatResult.code == NetEase.AntiCheatResult.OK) { string token = antiCheatResult.token; Debug.Log("token:" + token); } else { // 请根据错误码,检测相关代码 } } } #### 示例代码: Code (c#): // 异步接口,需新建类,继承 NetEase.GetTokenCallback, 并重写 onResult 方法 NetSecProtect.getTokenAsync(3000, "易盾提供的业务id", new MyGetToken()); ### 交互接口(ioctl) #### 接口用途: 1. 用于在客户端查询 SDK 采集的基础数据、设置需要传递给 SDK 数据(比如初始化配置内容、check 结果信息等)、及其他可能的定制功能服务。 2. 如果未调用初始化,此接口默认返回空字符串。 #### 接入须知: 接口调用前置条件是:调用了设置用户信息接口 (#4.2),并且设置了roleId等信息。 #### 函数原型: Code (c#): public static string ioctl(RequestCmdID request, string data); #### 参数说明: 参数 | 说明 | 必要性 request | 对应向风控系统请求的命令 | 必填 data | 设置信息的附加数据 | 可选,不需要可填null request值说明: Code (c#): public enum RequestCmdID { //初始化配置内容,防止初始化失败情况下,客户可以通过服务端请求初始化配置并传递给SDK Cmd_SetConfigData = 16, //客户服务端将check结果传递给SDK,便于执行后续动作 Cmd_SetResponseData = 17 }; #### 返回值: 错误的情况下,返回:unsupported request(不支持的命令);正确的情况下,返回对应命令的结果。 注意:该接口的返回值类型均为String,对返回值做判断的时候需要注意该值的类型。 #### 不同命令设置方法: ##### (1) 设置配置信息 向风控 SDK 配置传递从易盾服务器获取到的产品的配置信息(主要适用于风控 SDK 因被黑灰产屏蔽或其他原因导致无法正常获取配置信息的情况)。 配置信息: 初始化接口需设置callback 如果callback的code返回400,将msg发送到服务端,再发送到易盾服务端 易盾服务端的返回结果即为配置信息 示例代码: Code (c#): string ret = NetSecProtect.ioctl(RequestCmdID.Cmd_SetConfigData, config);//如果入参为null或空,则表示查询当前内存中配置版本;如果参数不为空,则表示更新初始化配置 返回值: 返回值为一个json: Code (java): {"s":0,"v":33554433}//s:状态,int类型,只有为0,v 字段的值才有意义; // v:版本,long类型(8字节),配置的版本 返回值 | 说明 s | 0:成功 -1:内存配置加载失败 v | 配置的版本号 ##### (2) 设置响应信息 向风控 SDK 配置传递从易盾服务端获取到的命中及响应结果信息,以便 SDK 执行相关处置动作(主要适用于风控 SDK 因被黑灰产屏蔽或其他原因导致无法正常获取响应结果的情况)。 响应结果信息: 调用获取凭证(getToken)接口,获取token 将token发送到服务端,在服务端调用check接口,获取结果,其中的 sdkRespData 即为 响应结果信息。 示例代码: Code (c#): string ret = NetSecProtect.ioctl(RequestCmdID.Cmd_SetResponseData, response); 返回值: 返回值为字符串格式: 返回值 | 说明 0或者-1 | 输入数据格式有误 1 | 解析成功 ### 安全通信协议接口 #### 接口用途: 该接口用于对通信数据进行白盒加密和白盒 HMAC 签名,加密和签名的密钥均会被隐藏,攻击者无法获取,从而保障应用/游戏的通信安全。 最新版本接口(V2.1)更新内容如下: - 自定义二进制格式,增大分析难度; - 多重加密,防明文传输; - 数据将进行校验,防止篡改; - 支持多算法,一旦加密算法被破解,可及时更新为另一种算法; - 一次一密,每次加密的密钥都不相同; - 自定义安全随机数发生器,防止系统随机数接口被篡改,始终生成一样的密钥; - 防重放攻击; - 防模拟执行(脱离Android/iOS环境运行)。 #### 接口须知: 如需使用该接口,请联系易盾获取详细说明文档。 ### 本地数据加解密接口 #### 接口用途: 该接口用于对应用/游戏本地存储的数据进行加解密,保护本地数据安全(游戏类型应用可用于本地游戏存档保护)。 #### 接口须知: 1. 加密后的数据,需要接入方自行存储,风控 SDK 只提供加密和解密功能。 2. 初始化接口的配置类必须设置gameKey 3. 若在unity中设置android 的targetSDK为30,运行时unity会输出如下log: Code (c++): AndroidJNIHelper:converting Byte array is obsolete, use SByte array instead 若出现该log,建议将要加密的数据先base64编码转换成string类型,再调用localSaveEncode接口。 1. 如果未调用初始化,此接口默认返回空字符串或全0 byte[]数组。 #### 函数原型: - 加密对象为 String 类型: Code (c#): public static string localSaveEncode(string inputData,int algIndex); public static string localSaveDecode(string inputData,int algIndex); - 加密对象为 byte[] 类型: Code (c#): public static string localSaveBytesEncode (byte[]inputData,int algIndex); public static byte[] localSaveBytesDecode (string inputData,int algIndex); #### 参数说明: 参数 | 说明 inputData | 需要加密或者解密的数据 algIndex | 加密 key 的绑定因子。参数为 0 时:因子为 APP 安装时间;参数为 1 时:因子为 APP 签名。 #### 返回值: - 若是加密接口,返回的数据即为原始数据的密文; - 若是解密接口,返回的数据即为密文对应的原始数据。 ### 模拟点击AI识别 ##### 接口用途: 批量的模拟点击极大的影响到游戏的正常,特别是工作室的参与,不仅影响到游戏的平台,还影响到游戏方的收入。易盾智能反外挂SDK提供相关的行为检测方案,使用模拟点击行为检测接口时,需要在游戏登录后,并且调用设置用户信息接口 (#4.2),设置role_id等信息后调用。 ##### 接入须知: SDK5.3.5以之后版本支持该接口 请在作弊情况较严重的玩法和场景下调用registerTouchEvent和unregisterTouchEvent,开启和关闭点击数据的采集,初次接入建议设置一个玩法和场景id,并同步给易盾,如需接入多个玩法和场景需提前与易盾沟通。 开启registerTouchEvent后,在该场景结束后必须调用unregisterTouchEvent关闭检测逻辑。 (1)开启采集数据 ##### 函数原型: Code (c#): public static void registerTouchEvent(int gameplayId,int sceneId) ##### 函数说明: 调用该接口后,开始采集点击事件的相关数据。 ##### 参数说明: 参数 | 说明 gameplayId | 玩法ID sceneId | 场景ID ##### 示例代码: Code (c#): NetSecProtect.registerTouchEvent(123,456); (2)关闭数据采集 ##### 函数原型: Code (c#): public static void unregisterTouchEvent() ##### 函数说明: 取消点击事件数据采集。 ##### 示例代码: Code (c#): NetSecProtect.unregisterTouchEvent();