一键登录
服务端调用前提条件:
服务端调用前提条件:
1、认证方案已经配置;2、认证sdk移动端已经集成;3、阿里云市场已经购买授权,已获取阿里云授权 appcode,appkey, appsecret (服务端调用时配置),可点击链接并登录阿里云管理控制台查看(https://market.aliyun.com/products/57124001/cmapi00036707.html )。 4.已激活产品U-Verify“(备注:点击可跳转至激活页面完成激活操作,带入参数:智能认证(U-Verify))
4、欢迎观看友盟学院出品《U-Verify服务端集成操作》,帮助开发者快速集成
1、请求
请求地址
https://verify5.market.alicloudapi.com/api/v1/mobile/info?appkey=*****&verifyId=****
-------------------------------------------------------------------------------------订购特殊客户按量计价商品的开发者不要请求以上资源包商品地址,请联系您的客服人员
*appkey为用户在友盟注册的应用分配的appkey, 与前提条件中阿里云授权的appkey不一样;_*该appkey可在友盟管理控制台的“认证管理”中获取,位置如下:
集成时appkey必须传递。-渠道商集成时若未传递appkey,会导致结果获取不正确;-非渠道商集成时若未传递appkey,会影响加密和用量统计;/ 参考 服务端签名 demo 代码时,host = verify5.market.alicloudapi.compath = /api/v1/mobile/infoappkey作为query参数传输*verifyId作为query参数传输(可选)如果开启超限管理功能, verifyId参数必传,否则设备阈值设定不生效(值通过SDK getVerifyId接口获取回传服务端 )
请求方法
POST请求头部
Content-Type: application/json; charset=UTF-8
//请求体类型。
Accept: application/json
//请求响应体类型,部分 API 可以根据指定的响应类型来返回对应数据格式,建议手动指定此请求头,如果不设置,部分 HTTP 客户端会设置默认值 */*,导致签名错误。
X-Ca-Version:1
// API 版本号,目前所有 API 仅支持版本号『1』,可以不设置此请求头,默认版本号为『1』。
X-Ca-Signature-Headers: X-Ca-Request-Mode,X-Ca-Version,X-Ca-Stage,X-Ca-Key,X-Ca-Timestamp
//参与签名的自定义请求头,服务端将根据此配置读取请求头进行签名,此处设置不包含 Content-Type、Accept、Content-MD5、Date 请求头,这些请求头已经包含在了基础的签名结构中,详情参照请求签名说明文档。
X-Ca-Stage: RELEASE //默认RELEASE
X-Ca-Key:60022326
//请求的 阿里云AppKey,通过云市场等渠道购买的 API 默认已经给 APP 授过权,阿里云所有云产品共用一套 AppKey 体系,删除 ApppKey 请谨慎,避免影响到其他已经开通服务的云产品。
X-Ca-Timestamp:1471864864235
//请求的时间戳,值为当前时间的毫秒数,也就是从1970年1月1日起至今的时间转换为毫秒,时间戳有效时间为15分钟。
X-Ca-Nonce:b931bc77-645a-4299-b24b-f3669be577ac
//请求唯一标识,15分钟内 AppKey+API+Nonce 不能重复,与时间戳结合使用才能起到防重放作用。
X-Ca-Signature:FJleSrCYPGCU7dMlLTG+UD3Bc5Elh3TV3CWHtSKh1Ys=
//请求签名,使用方参照签名机制生成。请求体
//HTTP Request Body json
{
"token":"******"//移动端回传token
}2、响应
状态码
200,400,500
http状态码,大于等于200小于300表示成功;大于等于400小于500为客户端错误;大于500为服务端错误;响应头
X-Ca-Request-Id:7AD052CB-EE8B-4DFD-BBAF-EFB340E0A5AF
//请求唯一 ID,请求一旦进入 API 网关应用后,API 网关就会生成请求 ID 并通过响应头返回给客户端,建议客户端与后端服务都记录此请求 ID,可用于问题排查与跟踪。
X-Ca-Error-Message:InvalidUrl
//API网关返回的错误消息,当请求出现错误时 API 网关会通过响应头将错误消息返回给客户。响应体
成功返回结果示例:
{"success":true,"data":{"mobile":"183xxxxxxxx","score":0.8,"activeScore":0.0},"code":2003,"message":"gain mobile's result and two evaluation score","requestId":"E70A813D-EB11-46D2-8473-84DF526E8284"}
失败返回结果示例:
{"success":false,"data":null,"code":-2219,"message":"AccessCode参数非法","requestId":"7AD052CB-EE8B-4DFD-BBAF-EFB340E0A5AF"}3、结果加密
1) 如果选择加密,请进入友盟管理控制台开启加密并获取秘钥;
点击链接进行加密设置,获取解密配置所需秘钥:https://ai.login.umeng.com/verify/secret
1、加密算法支持ECC,RSA ,目前ECC由于算法库问题,只支持Java,c# 调用;RSA 比较成熟,各语言可以找到对应库;
2、加密算法一旦选择,不可修改;
3、 ECC 算法库建议 bouncycastle 库(第三方的算法库,支持Java标准库里没有的算法)java 引入算法库
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>2) 加密结果示例:
{
"success":true,
"data":{
"mobile":"mHKL5J7aWYXWyAD9tpjO4w==",
"score":0.8,
"activeScore":0.0,
"aesEncryptKey":"MHsCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEYTBfAgEBBBiofs3Mhj8biFOmzyZz1iR1uVinR/mwsP+gCgYIKoZIzj0DAQGhNAMyAAQ0SHLd3+ds4y1K0bpBpzaeCaSEhEyXY4WHGoLlqv3tQ1nYDukSp5ks2qlR+Dkx4Pc="
},
"code":2003,
"message":"gain mobile's result and two evaluation score",
"requestId":"E70A813D-EB11-46D2-8473-84DF526E8284"
}3) 用户解密说明
A、返回结果只加密了手机号 , 加密方式 为AES 对称加密, 但是 AES加密时的密钥 (aesEncryptKey) 随机生成,经过 ECC/RSA(用户选择算法) 公钥加密返回用户.解密步骤:1、用在友盟产品控制台获取的 app对应私钥 解密 aesEncryptKey ,从而获得 AES密钥;2、用AES 密钥解密mobile, 获得手机号
B、伪代码示例:
字符串 privateKeyStr =产品控制台获取;
结果中--->获取 aesEncryptKey;
结果中--->获取 mobile;
byte[] byteArr = decryptAESKey( base64ToByte(aesEncryptKey),string2PrivateKey(privateKeyStr));//解密获aesKey
字符串 aesKey = byteToBase64(byteArr);
mobile =newString(decryptAES(base64ToByte(mobile),loadKeyAES(aesKey)))
解密完成C、java代码示例(ECC),可直接参考demo:解密手机号(ECC)demo java代码示例(RSA)也基本一致, 算法不一样; 可直接参考demo:解密手机号(RSA)demo
其他语言也可以参考代码逻辑:解密代码:
String privateKeyStr ="*****";//友盟产品控制台根据appkey获取
String aesEncryptKey =JSONObject.parseObject(response).getJSONObject("data").getString("aesEncryptKey");
String mobile =JSONObject.parseObject(response).getJSONObject("data").getString("mobile");
byte[] byteArr =ECCUtil.privateDecrypt(base642Byte(aesEncryptKey),string2PrivateKey(privateKeyStr));
String aesKey =Base64.getEncoder().encodeToString(byteArr);
mobile =newString(AESUtil.decryptAES(Base64.getDecoder().decode(mobile),AESUtil.loadKeyAES(aesKey)));私钥解密方法 ECCUtil.privateDecrypt
publicstaticbyte[] privateDecrypt(byte[] content,PrivateKey privateKey)throwsException{
Cipher cipher =Cipher.getInstance("ECIES","BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}将Base64编码后的私钥转换成PrivateKey对象方法: ECCUtil.string2PrivateKey
publicstaticECPrivateKey string2PrivateKey(String priStr)throwsException{
byte[] keyBytes = base642Byte(priStr);
PKCS8EncodedKeySpec keySpec =new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory =KeyFactory.getInstance("EC","BC");
ECPrivateKey privateKey =(ECPrivateKey)keyFactory.generatePrivate(keySpec);
return privateKey;
}base64 与字节数组互转
//字节数组转Base64编码
publicstaticString byte2Base64(byte[] bytes){
Encoder encoder =Base64.getEncoder();
return encoder.encodeToString(bytes);
}
//Base64编码转字节数组
publicstaticbyte[] base642Byte(String base64Key)throwsIOException{
Decoder decoder =Base64.getDecoder();
return decoder.decode(base64Key);
}AES对称解密: AESUtil.decryptAES
publicstaticbyte[] decryptAES(byte[] source,SecretKey key)throwsException{
Cipher cipher =Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(source);
}AES 将Base64编码后的AES秘钥转换成SecretKey对象 AESUtil.loadKeyAES
publicstaticSecretKey loadKeyAES(String base64Key)throwsException{
byte[] bytes = base642Byte(base64Key);
SecretKeySpec key =newSecretKeySpec(bytes,"AES");
return key;
}