先来简单介绍一下OAuth受权协议:OAUTH协议为用户资源的受权提供了一个安全的、开放而又简易的标准。同时,任何第三方均可以使用OAuth认证服务,任何服务提供商均可以实现自身的OAuth认证服务,于是OAUTH是开放的。业界提供了OAuth的多种实现如 PHP,JavaScript,Java,Ruby等各类语言开发包,大大节约了程序员的时间,于是OAuth是简易的。目前互联网不少服务如Open API,不少大头公司如Google,Yahoo,Microsoft等都提供了OAuth认证服务,这些都足以说明OAUTH标准逐渐成为开放资源受权 的标准。 java
你所开发的应用须要流程以下:
1. 向应用服务商也就是服务提供商(QQ、新浪、搜狐等微博)请求request_token。
2. 获得request_token后重定向用户到服务商的受权页面。
3. 若是用户选择受权你的应用,用request_token向服务商请求换取access_token。
4. 获得access_token等信息访问受限资源。
而服务商相应的响应以下:
1. 建立request_token返回给应用。
2. 询问用户是否受权此应用。若是用户受权重定向用户至应用页面。
3. 建立access_token并返回给应用。
4. 响应受限资源请求并返回相关信息。
通俗点的说法就是“你拿着你得身份证实(request_token)向服务商申请进入用户家的门钥匙(access_token),服务商询问用户同不一样意,若是用户赞成服务商就给你进入用户家门的钥匙(access_token),拿到钥匙后你就能够进到用户家里”。 程序员
做为一个开放协议目前有不少现成的Oauth库可供开发者使用,能够点击这里下载。不过有精力有时间的话仍是本身去实现一下OAuth受权的流程,能够很好的体会OAuth认证协议的原理。
下面就是我使用Java实现Oauth的具体步骤:
1、获取Request_token
首先得准备一下参数及其来源:
1. oauth_consumer_key —— 注册应用后由应用服务商提供
2. consumer_secret —— 注册应用后由应用服务商提供
3. oauth_callback —— 用户受权后的返回地址
4. oauth_nonce —— 随机字符串,须保证每次都不一样
5. oauth_timestamp —— 时间戳
6. oauth_signature_method —— 签名base string 的方法,目前支持 HMAC-SHA1
7. oauth_version —— Oauth协议版本
还须要下面三个请求地址(这些地址任何一个提供OAuth的服务商都会提供给你,看下API文档就会找到):
1. requst_token_url —— 上面第1步中的请求地址
2. authorize_url —— 上面第2步的请求地址
3. access_token_url —— 上面第3步的请求地址
至于如何注册应用,新浪微博点此,网易微博点此,腾讯微博点此,搜狐微博须要你发邮件索取,具体看这里。注册成功后就会得到oauth_consumer_key 和 consumer_secret 两个参数。
oauth_callback 起的做用是当用户受权成功后服务商会把用户重定向到这个网址。
oauth_nonce 是一个随机字符串下面是个人生成代码:
算法
public String set_nonce() { String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < 18; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); }
oauth_timestamp 是请求的时间戳,个人代码以下:
json
public String set_timestamp() { Date date = new Date(); long time = date.getTime(); return (time + "").substring(0, 10); }
须要说明一下的是这里的时间戳为10位而不是13位,所以截取0-10位置。
其余参数直接指定就好了。
接下来,有了这些参数就能够组装base string了。贮备base string的目的就是为了获得 oauth_signature 这个参数,这个参数向服务商发送请求的时候须要用到。
组装的方法是用下面8部分
1. POST(也能够是GET,取决于你应用服务商支持哪一个)。
2. Urlencode以后的requst_token_url 。
3. oauth_callback=Urlencode以后你的oauth_callback(Urlencode的参数为“utf-8”)。
4. oauth_consumer_key = 你的oauth_consumer_key
5. oauth_nonce = 你的oauth_nonce
6. oauth_signature_method = 你的 oauth_signature_method
7. oauth_timestamp = 你的oauth_timestamp
8. oauth_version = “1.0”——目前大多数OAuth都采用的是1.0或1.0a版本。
需 要注意的是上面除了1跟2外其余参数的格数形如: abc=“abc” ,而后先将上面1和2部分用&号相连获得串A、3-8部分用&相连获得串B,下面须要将串B再进行一次Urlencode获得串C,最后 将A跟C以&号相连就获得了base string。这个过程当中 oauth_callback 实质上通过了两次 Urlencode ,组装base string是很是容易出错的,一不当心丢一个引号或者格式稍有不对就会出错。
下面是个人Java实现代码:
安全
public String set_basestring() throws UnsupportedEncodingException { String bss; bss = oauth_request_method + "&" + URLEncoder.encode(requst_token_url, "utf-8") + "&"; String bsss = "oauth_callback=" + URLEncoder.encode(oauth_callback, "utf-8") + "&oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=" + oauth_signature_method + "&oauth_timestamp=" + oauth_timestamp + "&oauth_version=" + oauth_version; bsss = URLEncoder.encode(bsss, "utf-8"); return bss + bsss; }
有 了base string就能够签名生成oauth_signature这个参数,oauth_signature会在请求request_token的时候用到。签 名算法是HMAC-SHA1,签名的key就是最开始的consumer_secret后加一个&号,签名算法代码以下:
app
public String hmacsha1(String data, String key) { byte[] byteHMAC = null; try { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); mac.init(spec); byteHMAC = mac.doFinal(data.getBytes()); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException ignore) { } String oauth = new BASE64Encoder().encode(byteHMAC); return oauth; }
里面用的的BASE64Encoder这个类能够Google一个。
获得oauth_signature后就要开始向 requst_token_url 发送请求了,OAuth规范定义了三种传递OAuth参数方式:
1. httpheader中
2. url中
3. post form中
国内各大微博的支持状况是:新浪Httpheader可用,网易Httpheader可用,腾讯只支持在url,搜狐因为没有appkey因此还没去尝试。
若是使用Httpheader传递参数头名为“Authorization”,值为下面的格式,将值改成本身应用的。 dom
OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"
url和post form两种方式的参数名和参数值也即上面的,彻底同样。
请求发送成功后就会获得的响应以下:
post
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc& oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA& oauth_callback_confirmed=true
能够看到响应里面已经包含oauth_token和oauth_token_secret了。url