简介

Safety Detect提供:系统完整性检测(SysIntegrity)、应用安全检测(AppsCheck)、恶意URL检测(URLCheck)、虚假用户检测(UserDetect),可帮助保护应用程序免受安全威胁。

SysIntegrity API:系统完整性检测API,开发者通过该API评估其APP所运行的设备环境是否安全(如设备是否被root)。

AppsCheck API:恶意应用检测API,开发者可获取恶意应用列表。

URLCheck API:提供的恶意网址检测服务。可以使用此API来确定特定URL的威胁类型。

UserDetect API:虚假用户检测API,开发者可通过该API判断当前APP的交互对象是否为虚假用户。

您将建立什么

在这个Codelab中,您将使用已经创建好的Demo Project实现对华为系统完整性检测应用安全检测、恶意URL检测、虚假用户检测的API调用,通过Demo Project你可以体验到:
系统完整性检测:

应用安全检测:

恶意URL检测:

用户检测:

您将会学到什么

硬件要求

软件要求

集成HUAWEI HMS Core能力,需要完成以下准备工作

具体操作,请按照《HUAWEI HMS Core集成准备》中详细说明来完成。

打开服务开关

  1. 华为开发者联盟管理中心页面,点击"我的应用"->"应用名"->"开发"->"概览"->"API 管理"。
  2. 打开"Safety Detect"服务开关。

添加当前应用的AGC配置文件

  1. 华为开发者联盟管理中心页面,点击"我的应用"->"应用名"->"开发"->"概览",下载配置文件 "agconnect-services.json"
  2. 将下载的"agconnect-services.json"文件移至AndroidStudio开发工程app的根目录下。

添加SDK依赖

1.打开应用级的build.gradle文件。

2.在"dependencies"中添加编译依赖。

dependencies { // Add the following line implementation 'com.huawei.hms:safetydetect:4.0.0.300' }

配置混淆脚本

1.开发者编译APK前需要配置不要混淆HMS SDK,避免功能异常。

打开工程的混淆配置文件。

加入排除HMS SDK的混淆配置。

-ignorewarning -keepattributes *Annotation* -keepattributes Exceptions -keepattributes InnerClasses -keepattributes Signature -keepattributes SourceFile, LineNumberTable -keep class com.hianalytics.android.** {*; } -keep class com.huawei.updatesdk.** {*; } -keep class com.huawei.hms.** {*; }

2.如果开发者使用了AndResGuard,需要在混淆配置文件中加入AndResGuard白名单。

"R.string.hms*", "R.string.connect_server_fail_prompt_toast", "R.string.getting_message_fail_prompt_toast", "R.string.no_available_network_prompt_toast", "R.string.third_app_*", "R.string.upsdk_*", "R.layout.hms*", "R.layout.upsdk_*", "R.drawable.upsdk*", "R.color.upsdk*", "R.dimen.upsdk*", "R.style.upsdk*"

3.点击sync now 同步工程

系统完整性检测:

调用SysIntefrity API主要分为四个步骤:

  1. 获取 nonce。
  2. 请求 Safety Detect SysIntegrity。
  3. 在您的服务器中验证检测结果(签名,证书链,域名)。

获取nonce

在调用 Safety Detect SysIntegrity API 时,您必须传入一个 nonce 值。在检测结果中会包含这个 nonce 值,您可以通过校验这个 nonce来确定返回结果能够对应您的请求,并且没有被重放攻击。

一个 nonce 值只能被使用一次,nonce 值必须至少为 24 字节。推荐的做法是从发送到您的服务器的数据中派生 nonce 值。比如,使用用户名加当前时间戳作为 nonce 值。

请求 Safety Detect SysIntegrity

Safety Detect SysIntegrity 接口有两个参数,第一个是上一小节我们获取的 nonce 值,第二个是 appId。在开发准备中,您已经创建了一个应用,在 配置签名证书指纹 步骤中,您已经可以在开发者联盟的网页上获取 appId 了,将 appId 作为第二个参数传入接口:

private void invokeSysIntegrity() { SafetyDetectClient mClient = SafetyDetect.getClient(getApplicationContext()); // TODO(developer): Change the nonce generation to include your own, used once value, // ideally from your remote server. byte[] nonce = ("Sample" + System.currentTimeMillis()).getBytes(); Task task = mClient.sysIntegrity(nonce,"3*******"); task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() { @Override public void onSuccess(SysIntegrityResp response) { // Indicates communication with the service was successful. // Use response.getResult() to get the result data. String jwsStr = response.getResult(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // An error occurred while communicating with the service. if (e instanceof ApiException) { // An error with the HMS API contains some // additional details. ApiException apiException = (ApiException) e; // You can retrieve the status code using // the apiException.getStatusCode() method. Log.e(TAG, "Error: " + SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " + apiException.getStatusMessage()); } else { // A different, unknown type of error occurred. Log.e(TAG, "ERROR:" + e.getMessage()); } } }); }

服务端

建议对JwsResult的处理流程如下,其中校验证书和签名的部分,需要放在您APP的服务器端进行。

具体校验逻辑请获取示例代码,请下载

SafetyDetect-SysIntegrity-Sample

测试

安装测试apk,点击接口调用

应用安全检测:

示例代码为您演示如何完成应用安全检测API调用并获取检测结果;

客户端

您可直接调用Apps Check getMaliciousApps获取恶意应用列表

private void invokeGetMaliciousApps() { SafetyDetectClient appsCheckClient = SafetyDetect.getClient(MainActivity.this); Task task = appsCheckClient.getMaliciousAppsList(); task.addOnSuccessListener(new OnSuccessListener<MaliciousAppsListResp>() { @Override public void onSuccess(MaliciousAppsListResp maliciousAppsListResp) { // Indicates communication with the service was successful. // Use resp.getMaliciousApps() to get malicious apps data. List<MaliciousAppsData> appsDataList = maliciousAppsListResp.getMaliciousAppsList(); // Indicates get malicious apps was successful. if (maliciousAppsListResp.getRtnCode() == CommonCode.OK) { if (appsDataList.isEmpty()) { // Indicates there are no known malicious apps. Log.i(TAG, "There are no known potentially malicious apps installed."); } else { Log.i(TAG, "Potentially malicious apps are installed!"); for (MaliciousAppsData maliciousApp : appsDataList) { Log.i(TAG, "Information about a malicious app:"); // Use getApkPackageName() to get APK name of malicious app. Log.i(TAG, "APK: " + maliciousApp.getApkPackageName()); // Use getApkSha256() to get APK sha256 of malicious app. Log.i(TAG, "SHA-256: " + maliciousApp.getApkSha256()); // Use getApkCategory() to get category of malicious app. // Categories are defined in AppsCheckConstants Log.i(TAG, "Category: " + maliciousApp.getApkCategory()); } } } else { Log.e(TAG, "getMaliciousAppsList fialed: " + maliciousAppsListResp.getErrorReason()); } } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { // An error occurred while communicating with the service. if (e instanceof ApiException) { // An error with the HMS API contains some // additional details. ApiException apiException = (ApiException) e; // You can retrieve the status code using the apiException.getStatusCode() method. Log.e(TAG, "Error: " + SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " + apiException.getStatusMessage()); } else { // A different, unknown type of error occurred. Log.e(TAG, "ERROR: " + e.getMessage()); } } }); }

测试

点击"GET HARMFUL APPS LIST":

恶意URL检测:

调用URLCheck API主要分为四个步骤:

  1. 初始化URLCheck API。
  2. 请求网址检测。
  3. 关闭网址检测会话。
  4. 处理错误码。

初始化URLCheck API

在使用URLCheck API前,必须调用initUrlChecker()方法进行接口初始化,并且需要等待初始化完成后再进行接下来的接口调用,示例代码如下:

SafetyDetectClient client = SafetyDetect.getClient(getActivity()); client.initUrlCheck();

请求网址检测

指定关注的威胁类型,您可以将关注的威胁类型作为网址检测API的参数。 其中,UrlCheckerThreat类中的常量包含了当前支持的威胁类型:

package com.huawei.hms.safetydetect; public class UrlCheckerThreat { /** * 此类型URL被标记为包含潜在有害应用的页面的URL(篡改首页、网页挂马、恶意应用下载链接等) */ public static final int MALWARE = 1; /** * 这种类型的URL被标记为钓鱼、欺诈网站 */ public static final int PHISHING = 3; }

发起网址检测请求,待检测的URL包含协议、主机、路径,不包含查询参数。调用API示例代码如下:

String url = "https://developer.huawei.com/consumer/cn/"; SafetyDetect.getClient(this).urlCheck(url, appId, UrlCheckerThreat.MALWARE, UrlCheckerThreat.PHISHING) .addOnSuccessListener(this, new OnSuccessListener<SafetyDetectApi.URLCheckerResponse>() { @Override public void onSuccess(SafetyDetectApi.URLCheckerResponse urlResponse) { // 表示与服务通信已成功,识别检测到的威胁. if (urlResponse.getDetectedThreats().isEmpty()) { // 无威胁 } else { // 存在威胁! } } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // 与服务通信发生错误. if (e instanceof ApiException) { // HMS发生错误的状态码及对应的错误详情. ApiException apiException = (ApiException) e; Log.d(TAG, "Error: " + CommonStatusCodes .getStatusCodeString(apiException.getStatusCode())); // 注意:如果状态码是SafetyDetectStatusCode.ERROR_URL_CHECKER_API_NOT_INITIALIZED, // 这意味着您未调用initUrlChecker()或者调用未完成就发起了网址检测请求, // 或者在初始化过程中发生了内部错误需要重新进行初始化,需要重新调用initUrlChecker() } else { // 发生未知类型的异常. Log.d(TAG, "Error: " + e.getMessage()); } } });

获取网址检测的响应,调用返回对象URLCheckerResponse的getUrlCheckerResponse ()方法,返回List<UrlCheckerThreat>, 包含检测到的URL威胁类型。若该列表为空,则表示未检测到威胁,否则,可调用UrlCheckerThreat中的getUrlCheckResult ()取得具体的威胁代码。示例代码如下:

final EditText testRes = getActivity().findViewById(R.id.fg_call_urlResult); List<UrlCheckerThreat> list = urlCheckerResponse.getUrlCheckerResponse(); if (list.isEmpty()) { testRes.setText("ok"); } else { for (UrlCheckerThreat threat : list) { int type = threat.getUrlCheckResult(); } }

关闭网址检测会话

如果您的应用不再使用或长时间不再调用网址检测接口,请调用shutdownUrlChecker()方法关闭网址检测会话,释放资源:

SafetyDetect.getClient(this).shutdownUrlChecker();

测试

安装测试apk,以此点击接口调用

虚假用户检测:

示例代码分为两个部分:客户端部分展示API调用并获取检测结果;服务端部分展示如何获取虚假用户检测最终结果。

调用 UserDetect API

调用UserDetect API分为两步:

  1. 发起检测请求:调用UserDetect API的userDetection()方法以发起虚假用户检测请求,API会返回一个response token。
  2. 获取检测结果:使用步骤1获取response token调用云端verify获取检测结果:

发起检测请求

您需要通过调用userDetection发起检测。通常在用户点击UI组件(如一个按钮)后触发调用该方法。调用userDetection方法时,您需要做以下事情:

  1. 传入您申请的appId作为该方法的参数。
  2. 分别添加OnSuccessListener和OnFailureListener实例作为监听器。
  3. 重写onSuccess、onFailure,处理对应的结果。

调用该方法的示例代码如下所示:

final Task<UserDetectResponse> task = client.userDetection(APP_ID); task.addOnSuccessListener(new OnSuccessListener() { //success to get result from userDetection API @Override public void onSuccess(Object obj) { UserDetectResponse userDetectResponse = (UserDetectResponse) obj; String responseToken = userDetectResponse.getResponseToken(); //Send the response token to your own app server,so that you can get the final result //of user detect service. Replace the verify method with your own code here. String result = verify(responseToken); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { } });

获取检测结果

服务端主要分为两步:

  1. 获取accessToken;
  2. 调用云侧API获取检测结果。

具体步骤如下:

获取accessToken
详细请参考开放平台鉴权相关内容描述
调用云侧API获取检测结果:调用云侧获取结果。消息请求示例如下所示。

POST https://rms-api.cloud.huawei.com/rms/v1/userRisks/verify?appId=123456 HTTP/1.1 Content-Type: application/json;charset=utf-8 {"accessToken":"AAWWHI94sgUR2RU5_P1ZptUiwLq7W8XWJO2LxaAPuXw4_HOJFXnBlN-q5_3bwlxVW_SHeDPx_s5bWW-9DjtWZsvcm9CwXe1FHJg0u-D2pcQPcb3sTxDTJeiwEb9WBPl_9w","response":"bc9d6e73-b422-4d7c-8464-2a8b5ad5b525" }

更多关于请求接口的详细信息可以参照API参考

测试

安装测试apk,以此点击接口调用

下载完整功能的Demo源码。

safetydetect android sample

干得好,您已经成功完成了Codelab并学到了:

您可以阅读下面链接,了解更多相关的信息。

相关文档.

已复制代码