原文地址http://www.cnblogs.com/lingyun1120/archive/2012/07/11/2585767.html
- OAuth介绍
在分享过程中不可避免的会考虑到用户账户安全性的问题,第三方程序不应该直接接触用户账户信息,但是没有账户信息,又如何取得SNS平台的数据呢?OAuth很好的解决了这个问题,从第三方发起认证过程,在webview或者浏览器中完成认证过程,获得access token来代替账户密码,从而可以获取平台数据。OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。
- 国内各平台支持程度
SNS |
OAuth1.0a |
OAuth2.0 |
备注 |
新浪微博 |
不支持(曾经支持) |
支持 |
最近已经放弃1.0认证。但是1.0的开发文档还是可以学习。 |
腾讯微博 |
支持 |
支持 |
两者都支持,向2.0转变 |
QQ空间 |
不支持 |
支持 |
节操摆一边,文档干净清晰 |
人人 |
不支持 |
支持 |
人人文档很糟糕,用过的都知道 |
开心 |
支持 |
支持 |
两者都支持,向2.0转变 |
豆瓣 |
支持 |
不支持 |
豆瓣在开发平台方面确实做得不好,看它的文档就一目了然。 |
搜狐微博 |
支持 |
不支持 |
文档一般,logo素材太少 |
网易微博 |
支持 |
支持 |
文档一般,logo素材丰富 |
- 关于开发文档
文档地址:
新浪:http://open.weibo.com/wiki/%E9%A6%96%E9%A1%B5
空间:
腾讯:http://wiki.open.t.qq.com/index.php/%E9%A6%96%E9%A1%B5
人人:http://wiki.dev.renren.com/wiki/%E9%A6%96%E9%A1%B5
开心:http://open.kaixin001.com/document.php
豆瓣:http://www.douban.com/service/apidoc/
搜狐:http://open.t.sohu.com/en/%E9%A6%96%E9%A1%B5
网易:http://open.t.163.com/wiki/index.php?title=%E9%A6%96%E9%A1%B5
我们在进行开发时最重要的还是看平台的开发文档,而从开发文档也可以看出这个公司或者开发团队的专业程度。以下是我总结的各个平台的优缺之处,也给大家使用开发文档时增加一些帮助。
首先我觉得一个开放平台开发文档比较重要的几个点:OAuth文档、API文档、SDK、视觉(标示)素材、返回错误码说明这几个方面,当然这是从我现有的开发经验来选择,你可以根据实际情况侧重其他方面进行比较。
(BTW,8个平台中豆瓣的文档是最简陋的,而且许多接口也没有开放,无SDK,不过整体思路还是清晰的,开发时也不会有太多困惑,因此下面不再提及。)
OAuth文档:所有文档中以开心和腾讯微博做的最好,腾讯微博是有清晰示意图,本文也是引用他们的图片,而开心在于每个细节都描述的很清楚,在开发时不会有任何困惑的地方。最差的是人人和搜狐的文档,人人整体还是可以的,但是因为他们对于session key的处理让人很困惑,也不讲清楚,而且文档中有很多地方做的不够好,连请求参数都不列清楚,而搜狐在于他们的OAuth文档居然是外网的链接(包括OAuth官网地址,若干博客地址),既然做了就做完整。为了能够在搜狐认证成功,我最后在API列表中找到接口,在找到参数列表。其他平台的话,新浪稍好一点,其他半斤八两吧。
API文档:包含接口说明、访问权限、请求地址、支持格式、请求方式(POST/GET)、请求参数说明,返回结果(有例子)、字段说明。做的最好的是开心,除了这些说明,还会给出注意事项、调用示例、请求参数细分(api参数、OAuth1.0参数、OAuth2.0参数)。其他平台大同小异,不再赘述。
SDK:其实如果你不想了解OAuth认证以及调用API的细节之处,你完全可以使用它们的SDK。但是也有很多局限性:首先作为Android开发,有些网站不提供AndroidSDK(当然可以使用java SDK代替);其次SDK中很多代码你并不需要使用到(比如人人的支付功能),直接导入SDK包也会造成程序的臃肿;再者,如何我们需要修改SDK的一些功能,阅读SDK代码的代价也是很大的,每个平台的SDK整体结构也是天差地别。这些网站中,新浪、开心、腾讯微博的SDK比较好(后来和facebook的SDK相比较,大家都是各种借鉴啊)。而搜狐最让我伤心,居然什么SDK都没有……
视觉素材:搜狐提供的非常稀少,其他平台都有丰富的素材。
综上:开心网应该是做的比较好,为此我的demo主要是借鉴了它的SDK,给位读者可以去开心网自己下载SDK研究,下面是关于关于OAuth1.0和OAuth2.0的介绍,如果你已经了解,请直接无视吧。
Part 1:OAuth 1.0a
- OAuth1认证基本步骤:
- 获取未授权的Request Token(temporary credentials)
- 请求用户授权Request Token
- 使用授权后的Request Token换取Access Token(token credentials)
- 使用 Access Token 访问或修改受保护资源
- 请求签名
所有的OAuth请求使用同样的算法来生成(signature base string)签名字符基串和签名。
base string是把http方法名,请求URL以及请求参数用&字符连起来后做URL Encode编码。具体来讲,base string由http方法名,之后是&,接着是过url编码(url-encoded)之后的url和访问路径及&。接下来,把所有的请求参数包括POST方法体中的参数,经过排序(按参数名进行文本排序,如果参数名有重复则再安参数值进行重复项目排序),使用%3D替代=号,并且使用%26作为每个参数之间的分隔符,拼接成一个字符串。
private static String generateSignature(String baseString, String consumerKeySecret, String tokenSecret) { byte[] byteHMAC = null; try { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec spec; String oauthSignature = encode(consumerKeySecret) + "&" + ((tokenSecret != null) ? encode(tokenSecret) : ""); spec = new SecretKeySpec(oauthSignature.getBytes(), "HmacSHA1"); mac.init(spec); byteHMAC = mac.doFinal(baseString.getBytes()); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException ignore) { // should never happen } return new BASE64Encoder().encode(byteHMAC); }
- 获取未授权的Request Token
接口地址:
支持格式:OAuth HTTP 标准认证返回格式
HTTP请求方式:GET/POST
是否需要登录:否
请求参数:
参数名 | 必选 | 介绍 |
oauth_consumer_key | true | API Key(组件信息中的API Key值) |
oauth_signature_method | true | 签名方法,暂只支持HMAC-SHA1 |
oauth_signature | true | 签名值,密钥为:API Secret& |
oauth_timestamp | true | 时间戳,其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数 |
oauth_nonce | true | 单次值,随机生成的32位字符串(每次请求必须不同) |
oauth_callback | true | 认证成功后浏览器会被重定向到这个url中 |
oauth_version | false | 版本号,如果填写必须为1.0 |
scope | false | 以空格分隔的权限列表,若不传递此参数,代表请求默认的basic权限。 如需调用扩展权限,必需传递此参数, |
返回参数:
参数名 | 必选 | 意义 |
oauth_token | true | 未授权的Request Token |
oauth_token_secret | true | 对应的Request Token Secret |
oauth_callback_confirmed | true | 对oauth_callback的确认信号 (true/false) |
注:有一些平台不需要输入scope参数,在开发时请参照开发文档。
public boolean getRequestToken(Context context, String callbackUrl, String[] permissions) throws IOException { Bundle params = new Bundle(); params.putString("oauth_callback", callbackUrl); if (permissions != null && permissions.length > 0) { String scope = TextUtils.join(" ", permissions); params.putString("scope", scope); } params = Util.generateURLParams(OAUTH1_REQUEST_TOKEN_URL, GET_METHOD, params, CONSUMER_KEY, CONSUMER_SECRET, null); String response = Util.openUrl(context, OAUTH1_REQUEST_TOKEN_URL, GET_METHOD, params, null); if (response == null) { return false; } Bundle bundle = Util.decodeUrl(response); String token = (String) bundle.get(OUATH_TOKEN); String tokenSecret = (String) bundle.get(OUATH_TOKEN_SECRET); if (token == null || tokenSecret == null) { return false; } setRequestToken(token); setRequestTokenSecret(tokenSecret); return true; }
- 请求用户授权Request Token
接口地址:
支持格式:OAuth HTTP 标准认证返回格式
HTTP请求方式:GET/POST
是否需要登录:否
请求参数:
参数名 | 必选 | 意义 |
oauth_token | true | 上一步中获得的未授权的Request Token |
wap/client_type | false | 设置用户认证界面形式,PC还是mobile,参照各自文档 |
返回参数:
参数名 | 必选 | 意义 |
oauth_token | true | 用户授权之后的Token值,与未授权Token值相同 |
oauth_verifier | true | 验证码 |
- 使用授权后的Request Token换取Access Token
接口地址:
支持格式:OAuth HTTP 标准认证返回格式
HTTP请求方式:GET/POST
是否需要登录:否
请求参数:
参数名 | 必选 | 意义 |
oauth_consumer_key | true | API Key |
oauth_token | true | 第一步中获得的Request Token |
oauth_signature_method | true | 签名方法,暂只支持HMAC-SHA1 |
oauth_signature | true | 签名值,(密钥为:API Secret&Request Token Secret) |
oauth_timestamp | true | 时间戳, 其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数 |
oauth_nonce | true | 单次值,随机生成的32位字符串,防止重放攻击(每次请求必须不同) |
oauth_verifier | true | 上一步请求授权request token时返回的验证码 |
oauth_version | flase | 版本号,如果填写必须为1.0 |
返回参数:
参数名 | 必选 | 意义 |
oauth_token | true | Access Token |
oauth_token_secret | true | Access Token Secre |
public boolean getAccessToken(Context context, String requestToken, String requestTokenSecret, String verifier) throws IOException { Bundle params = new Bundle(); params.putString(OUATH_TOKEN, requestToken); if (verifier != null) params.putString(OUATH_TOKEN_VERIFIER, verifier); params = Util.generateURLParams(OAUTH1_ACCESS_TOKEN_URL, GET_METHOD, params, CONSUMER_KEY, CONSUMER_SECRET, requestTokenSecret); String response = Util.openUrl(context, OAUTH1_ACCESS_TOKEN_URL, GET_METHOD, params, null); if (response == null) { return false; } Bundle bundle = Util.decodeUrl(response); String token = (String) bundle.get(OUATH_TOKEN); String tokenSecret = (String) bundle.get(OUATH_TOKEN_SECRET); if (token == null || tokenSecret == null) { return false; } setAccessToken(token); setAccessTokenSecret(tokenSecret); return true; }
Part 2:OAuth 2.0
OAuth2.0和OAuth1.0的区别还是在于简化了认证过程,不需要从未授权的Request Token转化到授权Request Token,而是利用app key通过用户授权生成access token但是,与1.0的不同之处是access token有自身的有效期,且不同平台、不同级别的程序有着不同的有效期,在程序开发中一定记得判断access token是否过期,对于过期之后的处理方法主要是利用access token和refresh token重新生成access token或者重新利用app key向服务器发送请求生成access token。由于这个问题,与OAuth1.0基本一致不一样,各个平台OAuth2.0做了不一样的选择。
OAuth2.0服务支持以下获取Access Token的方式:
a. Authorization Code:Web Server Flow,适用于所有有Server端配合的应用。
b. Implicit Grant:User-Agent Flow,适用于所有无Server端配合的应用。
因为demo是无服务器的程式,所以我们采用Implicit Grant:User-Agent Flow的获取方式。
- 获取Access Token
为了获取Access Token,应用需要将用户浏览器(或手机/桌面应用中的浏览器组件)到OAuth2.0授权服务的“http://xxxxxxxxx/authorize”地址上,并带上以下参数:
参数名 | 必选 | 介绍 |
client_id | true | 申请组件时获得的API Key |
response_type | true | 此值固定为“token” |
redirect_uri | true | 授权后要回调的URI,即接受code的URI。对于无Web Server的应用, 其值可以是“oob”。 |
scope | false | 以空格分隔的权限列表,若不传递此参数,代表请求默认的basic权限。 如需调用扩展权限,必需传递此参数 |
state | false | 用于保持请求和回调的状态,授权服务器在回调时(重定向用户 浏览器到“redirect_uri”时),会在Query Parameter中原样回传该参数 |
display | false | 登录和授权页面的展现样式,默认为“page”。手机访问时,此参数无效 |
client | false | 是否为手机访问。手机访问:client=1;不是手机,无需次参数 |
若用户登录并接受授权,授权服务将重定向用户浏览器到“redirect_uri”,并在Fragment中追加如下参数:
参数名 | 介绍 |
access_token | 要获取的Access Token |
expires_in | Access Token的有效期,以秒为单位 |
refresh_token |
用于刷新Access Token 的 Refresh Token 一些平台不返回这个参数,需要程序员进行判断处理 |
scope |
Access Token最终的访问范围,即用户实际授予的权限列表 |
state | 如果请求获取Access Token时带有state参数,则将该参数原样返回 |
- 人人网和QQ空间的后续操作
人人网获得access token还需要获得session key和session secret,然后再调用api接口的时候利用app key、session key以及sig(签名认证,点击此处查看详细算法),最近人人说可以使用access token来替换app key和session key的组合,貌似不需要session key,但是sig参数又需要通过session key才能获得,真是多此一举。
public void getRenrenSessionKey(Context context, String accessToken) { if (accessToken == null || accessToken.length() < 1) { return; } Bundle params = new Bundle(); params.putString("oauth_token", accessToken); try { String sk = Util.openUrl( "http://graph.renren.com/renren_api/session_key", "POST", params); JSONObject obj = new JSONObject(sk); String error = obj.optString("error", null); if (error != null) { throw new SNSAuthError(obj.toString(), null, null); } String sessionKey = obj.getJSONObject("renren_token").getString( "session_key"); String sessionSecret = obj.getJSONObject("renren_token").getString( "session_secret"); long uid = obj.getJSONObject("user").getLong("id"); // 服务器返回的过期时间单位为秒,故乘以1000 long expires = obj.getJSONObject("renren_token").getLong( "expires_in") * 1000; long current = System.currentTimeMillis(); long expireTime = current + expires; setSeeionKey(sessionKey); setSeeionSecret(sessionSecret); setSeeionExpires(expireTime); Log.i(Util.LOG_TAG, "---login success sessionKey:" + sessionKey + " expires:" + expires + " sessionSecret:" + sessionSecret + " uid:" + uid); } catch (JSONException e) { throw new RuntimeException(e.getMessage(), e); } }
QQ空间没有人人网这么麻烦,只是在返回参数中多了一个openId参数,这个参数在调用api接口是需要传入,除此之外没什么特殊之处,openid估计是为了他们平台的统一性设计的,无大碍。
public void getQzoneOpenId(Context context, String accessToken) { if (accessToken == null || accessToken.length() < 1) { return; } Bundle params = new Bundle(); params.putString("access_token", accessToken); String open = Util.openUrl("https://graph.z.qq.com/moc2/me", "GET", params); String[] param = open.split("&"); String[] openid = param[1].split("="); setOpendId(openid[1]); }
Summary
OAuth认证其实很简单,调用api也是根据各个平台进行些许的调整而已,在进行开发的过程更细心的一点应该没什么问题,如果你有问题,欢迎大家来交流。关于代码的问题,大家把平台上相关的SDK下载下来稍微研究一下就可以了,本人是利用开心网的SDK修改的,新浪和腾讯的都不错,以上信息,仅作参考,如有错误之处,望指正!谢谢!
过段时间在完成《国外篇》,流程类似,主要还是介绍各自特点吧,OAuth不再赘述。
相关推荐
C#是Microsoft开发的一种面向对象的编程语言,广泛应用于Web应用开发,包括OAuth认证。对于初学者来说,理解并实现OAuth认证流程在C#中是非常重要的一步。 OAuth认证通常涉及到四个主要角色:资源所有者(Resource ...
OAuth认证是一种广泛应用于移动应用和Web服务中的授权框架,它允许第三方应用在用户授权的情况下,安全地访问用户的个人信息或者特定服务。在这个场景中,我们提到的是如何利用OAuth认证结合网易微博开放平台来实现...
在“Oauth认证流程学习代码”中,我们将深入理解OAuth的基本流程和相关代码实现。OAuth的流程主要包括四个角色:资源所有者(Resource Owner)、客户端(Client)、资源服务器(Resource Server)和授权服务器...
在"my_oauth"这个文件夹中,可能包含了关于如何实现OAuth认证的代码示例、配置文件或者教程文档,帮助开发者理解和实践OAuth认证流程。对于开发人员来说,理解并正确实施OAuth认证流程至关重要,以便在实际项目中...
3./class/下,文件名中含有If的文件,定义的是接口.总计3个接口文件:各个网站的api访问路径(urlIf)、申请到的appkey接口(keyIf),返回的参数名接口(paramIf)。...本例中的OAuth客户端来源于新浪微博OAuth认证SDK。
weibo oauth 认证jar包 cas应用weibo集成
【标题】:“新浪微博API OAuth认证”是一个关于使用OAuth授权机制与新浪微博API进行交互的技术主题。OAuth是一种开放标准,允许用户提供一个令牌,而不是用户名和密码来访问他们存储在特定服务提供者的数据。在微博...
OAuth认证是一种广泛应用于互联网服务中的授权框架,它允许第三方应用在用户无需透露其登录凭证的情况下,访问特定的受保护资源。OAuth认证的核心理念是让用户控制第三方应用如何访问他们的数据,而无需分享自己的...
OAuth认证是一种开放标准,用于授权第三方应用访问用户在特定服务上的资源,如微博、社交网络或云存储。在Android平台上,开发者需要理解如何实现OAuth来让应用与新浪、腾讯、人人网、豆瓣以及Facebook等社交媒体...
新浪、腾讯、网易、搜狐微薄OAuth认证整合Android版
### 关于微博服务端API的OAuth认证实现 #### 核心知识点概述 本文将围绕微博服务端API的OAuth认证实现这一主题展开详细讨论。主要内容包括OAuth认证的基本原理、微博服务端API的工作机制以及如何实现OAuth认证的...
豆瓣OAuth认证示例项目是一个用于演示如何通过OAuth协议在应用中实现与豆瓣API的授权交互的实例。OAuth(开放授权)是一种开放标准,允许用户提供一个令牌,而不是用户名和密码来访问他们存储在特定服务提供者的数据...
腾讯微博的OAuth认证则是腾讯为开发者提供的一种安全接入其微博平台的机制,让开发者能够通过用户的授权来获取接口权限,进而发布、读取或更新用户的相关信息。 OAuth认证的核心流程包括以下几个步骤: 1. **请求...
Android版新浪、网易、腾讯、搜狐微博OAuth认证实例集,想更多了解OAuth认证的朋友,请下载java源码包,在示例中完整解析了OAuth认证的过程:定义URL编码方式,请求url,得到注册应用后服务商提供的key和secret,...
在Android平台上进行微博(Sina)OAuth认证是一种常见的第三方登录或数据获取方式。OAuth,全称是开放授权协议,它允许用户让第三方应用在不获取用户名密码的情况下,安全地访问存储在另一服务提供者上的个人信息。...
在Go语言中实现OAuth认证,可以让开发者安全地集成第三方服务,比如Google、Facebook或Twitter等。本文将详细介绍如何在Go语言中实现OAuth认证,并提供代码示例。 在Go语言中实现OAuth认证是一个涉及多个步骤的过程...
OAuth认证在Android开发中是一个重要的知识点,特别是在移动应用与第三方服务集成时,如社交媒体登录、云存储服务等。OAuth允许用户授权第三方应用访问其私有资源,而无需分享用户名和密码,增强了安全性。本示例是...
本主题聚焦于“新浪微博上传图片”与“OAuth认证”的过程,这两个概念是开发者进行微博应用开发时不可或缺的知识点。 OAuth(开放授权)是一种授权框架,允许第三方应用在用户无需共享其账号密码的情况下,安全地...