小米帐号OAuth 2.0互通接口应用学习
2015-05-23 08:37
1586 查看
最近,在做一个和小米账号互通的第三方登陆接口,详细的学习了小米开发者文档,下面对接口文档的学习进行总结和汇总。
用户(user):存放在服务提供方的受保护的资源的拥有者。
客户端(client):要访问服务提供方资源的第三方应用,通常是网站在认证过程之前,客户端要向服务提供者申请客户端标识。
令牌(token):分发给客户端的代表访问授权的字符串。通常这个字符串对客户端来说是不透明的。令牌代表资源拥有者许可的访问作用域和持续时间,并由资源服务器和授权服务器强制保证。这个令牌可以代表一个标识符,用于检索授权信息,或以一种可验证的方式自包含授权信息(即一个包含数据和签名的令牌字符串)。令牌可能只代表纯粹的访问能力。
访问令牌(access token):客户端用来代表资源拥有者发送验证请求的令牌。 小米API将支持OAuth 2.0中Bearer Token和MAC Token的两种token形式。
刷新令牌(refresh token):客户端用来获取新的访问令牌的令牌,而不用资源拥有者的参与。
授权码(code):一个短期令牌,代表终端用户的授权。授权码用于获取一个访问令牌和一个刷新令牌。
客户端标识符(client id):分发给客户端的唯一标识,用于客户端向授权服务器标识自己。客户端标识符可以有一个对应的密钥。
2.1请求用户授权接口
URL: https://account.xiaomi.com/oauth2/authorize
HTTP请求方: GET
请求用户授权参数表
接口返回值
response_type为code(Authorization Code Flow)时接口返回值:
2.2 获取访问令牌接口
URL : http://account.xiaomi.com/oauth2/token
HTTP请求方式: GET
获取访问令牌参数表
接口返回值
接口返回值是一个Json格式字符串,具体说明如下:
第三方获取访问令牌验证通过,该接口返回Access Token相关的信息:
{
“access_token”: “access token value”,
“expires_in”: 360000,
“refresh_token”: “refresh token value”,
“scope”: “scope value”,
“token_type “: “mac”,
“mac_key “: “mac key value”,
“mac_algorithm”: ” HmacSha1”
“openId”=”2.0XXXXXXXXX”
}
字段说明:
1. access_token:获取的Access Token;
2. expires_in:Access Token的有效期,以秒为单位;
3. refresh_token:用于刷新Access Token ,有效时间为10年;
4. scope:Access Token最终的访问范围,既用户实际授予的权限列表;
5. token_type: access token的类型,type值为mac;
6. mac_key: MAC加密算法对请求进行加密时的密钥;
7. mac_algorithm:MAC加密的算法,目前只支持HmacSha1
8. openId: 是v2版本所提供的一种唯一标识
2.3获取用户名片
URL: https://open.account.xiaomi.com/user/profile
HTTP请求方式:GET
获取用户名片参数表
返回数据
正确返回:
如果访问令牌验证通过,会返回用户相关的信息, 返回格式为Json文本, 格式如下:
{
“result”: “ok”,
“description”: “成功”,
“data”: {
“miliaoNick”: “米聊昵称”,
“userId”: 米聊号,
“miliaoIcon”: 头像URL
},
“code”: 0
}
错误返回
如果访问令牌验证错误,会返回错误信息, 返回格式为Json文本, 格式如下:
{
“result”: “error”,
“description”: “错误描述”,
“code”: 错误码
}
Java算法示例
PHP算法示例
3.1请求内容标准化
使用Mac Token需要将请求内容按照一定的规则拼接形成符合要求的标准的格式字符串,标准化字符串用于计算请求API的签名值,小米规定的格式请求字符串格式如下(\n代表换行):
格式化字符串 = Nonce + \n + HTTP方法 + \n + HOST + \n + URI+ \n + QUERY+\n
具体示例:
请求字符串=54897465748976549:21459478\nGET\n open.account.xiaomi.com\n/user/profile\n
clientId=xxx&token=xxx\n
3.2MacToken请求格式
采用Mac Token调用API,需要将相关签名信息放入请求的http请求的Header中。第三方在发送API请求时,要对请求进行MAC加密计算,并将结果放到请求Header中的”Authorization”字段中。
Authorization字段内容如下:
Authorization: MAC access_token=”token value”,nonce=”随机码” ,mac=”签名值”
字段含义说明:
1. access_token : 授权时下发的access_token。
2. nonce:随机串,由客户端按照2中规则产生的随机字符串包括当前分钟数值。
3. mac:签名值,根据mac算法计算生成的。Mac = HmacSha1(格式化字符串, mac_key)。
相关方法的源代码
1.相关名词的解释
服务提供方(resource server): 用户使用服务提供方来存储受保护的资源,这里指的是小米公司。用户(user):存放在服务提供方的受保护的资源的拥有者。
客户端(client):要访问服务提供方资源的第三方应用,通常是网站在认证过程之前,客户端要向服务提供者申请客户端标识。
令牌(token):分发给客户端的代表访问授权的字符串。通常这个字符串对客户端来说是不透明的。令牌代表资源拥有者许可的访问作用域和持续时间,并由资源服务器和授权服务器强制保证。这个令牌可以代表一个标识符,用于检索授权信息,或以一种可验证的方式自包含授权信息(即一个包含数据和签名的令牌字符串)。令牌可能只代表纯粹的访问能力。
访问令牌(access token):客户端用来代表资源拥有者发送验证请求的令牌。 小米API将支持OAuth 2.0中Bearer Token和MAC Token的两种token形式。
刷新令牌(refresh token):客户端用来获取新的访问令牌的令牌,而不用资源拥有者的参与。
授权码(code):一个短期令牌,代表终端用户的授权。授权码用于获取一个访问令牌和一个刷新令牌。
客户端标识符(client id):分发给客户端的唯一标识,用于客户端向授权服务器标识自己。客户端标识符可以有一个对应的密钥。
2.授权接口说明
授权码方式(authorization code)获取访问令牌(access token)的授权验证流程又被称为web server flow,适用于所有有服务端的应用,如Web/Wap站点、有服务端的手机/桌面客户端应用等。2.1请求用户授权接口
URL: https://account.xiaomi.com/oauth2/authorize
HTTP请求方: GET
请求用户授权参数表
名称 | 必须 | 范围 | 说明 |
---|---|---|---|
client_id | true | Long | 申请应用时分配的App Id。 |
redirect_uri | true | String | 授权回调地址,必须和申请应用是填写的一致。 |
response_type | true | String | 描述获取授权的方式,目前只支持code 和 token,Code 对应 Authorization |
Code | true | String | Flow, token对应Implicit Flow。 |
scope | false | String | 申请scope权限所需参数,可一次申请多个scope权限,用空格分隔。 |
state | false | String | 用于保持请求和回调的状态,在回调时,会在Query Parameter中回传该参数。 |
skip_confirm | false | Boolean | 是否跳过帐号确认过程,黄页接入请设置为true(skip_confirm=true) |
response_type为code(Authorization Code Flow)时接口返回值:
名称 | 必须 | 范围 | 说明 |
---|---|---|---|
code | True | String | 用于调用access_token,接口获取授权后的access token。 |
state | False | String | 如果请求时传递参数,会回传该参数。 |
URL : http://account.xiaomi.com/oauth2/token
HTTP请求方式: GET
获取访问令牌参数表
名称 | 必须 | 范围 | 说明 |
---|---|---|---|
client_id | True | Long | 申请应用时分配的App Id。 |
redirect_uri | True | String | 授权回调地址,必须和申请应用是填写的一致。 |
client_secret | True | String | 申请应用时分配的App Secret |
grant_type | True | String | 此值为authorization_code 或者 refresh_token |
refresh_token | False | String | 当grant_type为refresh_token时,必须传该参数,置为上次下发的 |
code | False | String | 当grant_type为authorization_code时,必须传该参数,置为上次下发的code值 |
token_type | True | String | 说明返回的token类型,目前是mac |
接口返回值是一个Json格式字符串,具体说明如下:
第三方获取访问令牌验证通过,该接口返回Access Token相关的信息:
{
“access_token”: “access token value”,
“expires_in”: 360000,
“refresh_token”: “refresh token value”,
“scope”: “scope value”,
“token_type “: “mac”,
“mac_key “: “mac key value”,
“mac_algorithm”: ” HmacSha1”
“openId”=”2.0XXXXXXXXX”
}
字段说明:
1. access_token:获取的Access Token;
2. expires_in:Access Token的有效期,以秒为单位;
3. refresh_token:用于刷新Access Token ,有效时间为10年;
4. scope:Access Token最终的访问范围,既用户实际授予的权限列表;
5. token_type: access token的类型,type值为mac;
6. mac_key: MAC加密算法对请求进行加密时的密钥;
7. mac_algorithm:MAC加密的算法,目前只支持HmacSha1
8. openId: 是v2版本所提供的一种唯一标识
2.3获取用户名片
URL: https://open.account.xiaomi.com/user/profile
HTTP请求方式:GET
获取用户名片参数表
名称 | 必须 | 范围 | 说明 |
---|---|---|---|
clientId | True | Long | 申请应用时分配的App Id。 |
token | True | String | 用户授权时client得到的token |
Header数据 | True | 详见下文 | 按照小米提供的算法生成Header授权信息。 |
正确返回:
如果访问令牌验证通过,会返回用户相关的信息, 返回格式为Json文本, 格式如下:
{
“result”: “ok”,
“description”: “成功”,
“data”: {
“miliaoNick”: “米聊昵称”,
“userId”: 米聊号,
“miliaoIcon”: 头像URL
},
“code”: 0
}
错误返回
如果访问令牌验证错误,会返回错误信息, 返回格式为Json文本, 格式如下:
{
“result”: “error”,
“description”: “错误描述”,
“code”: 错误码
}
3.Mac Token详细说明
MacToken是授权小米下发的一种访问令牌类型,使用MacToken调用API时,用MAC加密算法对请求进行加密,并将结果放到http请求的header中。MAC算法有HmacSha1和HmacSha256两种,小米API默认使用HmacSha1。Java算法示例
public static byte[] encryptHMACSha1(byte[] data, byte[] key) { SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1); Mac mac = Mac.getInstance(HMAC_SHA1); mac.init(signingKey); mac.update(data); return mac.doFinal(); }
PHP算法示例
static public function buildSignature($signString, $secret) { $sign = base64_encode(hash_hmac('sha1', $signString, $secret, True)); return urlencode($sign); }
3.1请求内容标准化
使用Mac Token需要将请求内容按照一定的规则拼接形成符合要求的标准的格式字符串,标准化字符串用于计算请求API的签名值,小米规定的格式请求字符串格式如下(\n代表换行):
格式化字符串 = Nonce + \n + HTTP方法 + \n + HOST + \n + URI+ \n + QUERY+\n
属性 | 说明 | 示例 |
---|---|---|
Nonce | 由随机数和时间戳组成,格式:随机数:当前分钟数 | |
HTTP方法 | 调用API时请求方式 | GET/ POST |
HOST | 调用API时的域名 | open.account.xiaomi.com |
URI | 调用API时的path(必须以/开头) | /user/profile |
QUERY Key | 按照字典序排列的query串,内容为空的去query字段不参与签名 | clientId=xxx&token=xxx |
请求字符串=54897465748976549:21459478\nGET\n open.account.xiaomi.com\n/user/profile\n
clientId=xxx&token=xxx\n
3.2MacToken请求格式
采用Mac Token调用API,需要将相关签名信息放入请求的http请求的Header中。第三方在发送API请求时,要对请求进行MAC加密计算,并将结果放到请求Header中的”Authorization”字段中。
Authorization字段内容如下:
Authorization: MAC access_token=”token value”,nonce=”随机码” ,mac=”签名值”
字段含义说明:
1. access_token : 授权时下发的access_token。
2. nonce:随机串,由客户端按照2中规则产生的随机字符串包括当前分钟数值。
3. mac:签名值,根据mac算法计算生成的。Mac = HmacSha1(格式化字符串, mac_key)。
相关方法的源代码
static long localTimeDiff = dateDiff(DateTime.Now, getServerTime()); static private Random ran = new Random(Dns.GetHostName().GetHashCode()+ (int)DateTime.Now.Ticks);//根据主机名的hashcode和现在时间得到随即种子; /** * 获取时间差(注意时区) * @param DateTimeStart时间开始 * @param DateTimeEnd时间结束 * @return 得到时差 */ static long dateDiff(DateTime DateTimeStart, DateTime DateTimeEnd) { long dateDiff = 0; TimeSpan end = new TimeSpan(DateTimeEnd.Ticks); TimeSpan start = new TimeSpan(DateTimeStart.Ticks); TimeSpan diff = end.Subtract(start).Duration(); dateDiff = (diff.Days * 24 + diff.Hours); dateDiff = dateDiff * 60 + diff.Minutes; Console.WriteLine("get the timediff " + dateDiff); return dateDiff; } /** * 得到header的值 * @param nonce为随机数 * @param mac为mac加密的值 * @param accessToken为访问令牌 * @return 得到header的值 */ static public String createHeader(string nonce, string mac, string accessToken) { string header = string.Format("MAC access_token=\"{0}\",nonce=\"{1}\",mac=\"{2}\"", Uri.EscapeDataString(accessToken), Uri.EscapeDataString(nonce), Uri.EscapeDataString(mac)); return header; } /** * 得到HMACSHA1加密的密文(密文格式为nonce + \n + method(POST\GET) + \n + host + \n + uriPaht + \n + req(queryparam按照key的字典序)+\n(最后也需要添加一个\n)) * @param nonce为随机数 * @param query为请求 * @param method http方法,填“GET”或“POST” * @param localPath使用参数详情看sdk文档 * @param macKey,hmacsha1的密钥 * @return 得到HMACSHA1加密的密文 */ static public String createCiphertext(string nonce, string query, string method, string localPath, string macKey) { method = method.ToUpperInvariant(); string ciphertext = nonce + "\n" + method + "\n" + XiaoMiHttpClientConst.hostURI + "\n" + localPath + "\n" + query + "\n"; HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.UTF8.GetBytes(macKey); byte[] dataBuffer = Encoding.UTF8.GetBytes(ciphertext); byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); ciphertext = Convert.ToBase64String(hashBytes); return ciphertext; } /** * 得到服务器现在的时间 * @param * @return 得到服务器现在的时间 */ static public DateTime getServerTime() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(XiaoMiHttpClientConst.apiURI); request.Method = "GET"; HttpWebResponse response; Console.WriteLine("waiting for getting the server time"); try { response = (HttpWebResponse)request.GetResponse(); } catch (WebException ex) { response = (HttpWebResponse)ex.Response; } if (response == null) Console.WriteLine("error: can not get the server time ,please check the network connections"); return response.LastModified; } /* * 得到Nonce用 随机数:时间分钟差 为格式 * @param * @return Nonce */ static public string getNonce() { //产生随机数过程 int randKey = ran.Next(); string nonce = randKey + ":" + (dateDiff(new DateTime(1970, 1, 1, 8, 0, 0), DateTime.Now) + localTimeDiff); return nonce; }
相关文章推荐
- 使用HttpClient 访问Spring OAuth 2.0接口 获取token
- JAVA学习--接口的应用:工厂方法的设计模式
- 学习node js 之微信公众帐号接口开发 准备工作
- Flex 学习之路之六 用户接口user interface 应用效果effect
- Python模块学习之hashlib-MD5在接口测试中的应用
- Fiori2.0学习笔记-OData的应用
- php学习笔记---面向对象中[接口]与[多态性]的应用
- spring-cloud-starter-feign 组件在spring boot中的应用:访问Oauth2资源服务器的资源接口
- Flask 学习 十三 应用编程接口
- IDC3516电流环隔离接口芯片的应用 转 学习
- 深入学习Lock锁(5)——Condition接口应用与分析
- OAuth 2.0 学习
- ASP.NET 2.0 学习笔记 1: session 与 script 应用
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
- 学习php微信开发应用接入API接口笔记
- V4L2 学习笔记2-应用接口分析
- 学习接口应用之C#接口实例
- 一个不错的学习OAuth 2.0网站。英文