OAuth 2.0理解与第三方应用发微博实例

先介绍一下关于OAuth2.0的相关理论,如果不想看的可以直接跳到下面的PYTHON实现第三方登录发微博实例PHP实现第三方登录发微博


理论解释

OAuth 2.0是什么

OAuth(Open Authorization)是一种协议,被广泛运用于验证与授权领域。现在最新版本是2.0。

OAuth 2.0的目的

官方描述RFC5849是这么描述的:

  • 允许第三方应用从HTTP服务器获得一定权限
  • 允许第三方应用在用户批准下代表用户与服务器进行交互
  • 允许第三方应用获得代表用户的权限

那么通俗来讲:

  • 第三方应用在用户批准下获得服务商里储存的用户个人信息(什么值得买网站使用微博账号登陆,并获得用户微博账号里的名字)
  • 第三方应用代表用户去与服务器交互(虾米音乐你的名义发了一条分享音乐的微博)
  • 用户无需提供账户密码给第三方应用的(什么值得买虾米音乐服务器并不会储存你的微博账号密码

总结一下,就是通过OAuth协议能够让用户给各种第三方应用分发特定的令牌,这个令牌是有时间限制,有权限控制,访问特定资源的,而第三方应用就握着这个令牌去做些对用户来说有意义的事情。

OAuth 2.0的授权流程

OAuth2.0 授权过程
(A).客户端(Client)向用户(Resource Owner)发起请求授权(Authorization Request).
(B).用户(Resource Owner)批准了客户端(Client)的请求授权(Authorization Grant).
(C).客户端(Client)用上一步的用户授权许可(Authorization Grant),向服务器(Authorization Server)请求一个令牌(Access Token).
(D).服务器(Authorization Server)核实了用户授权许可,发放了一个令牌(Access Token)给客户端(Client).
(E).客户端(Client)用上一步获得的令牌(Access Token)向资源服务器(Resource Server)请求一些需要授权的资源(Protected Resource).
(F).资源服务器(Resource Server)核实了令牌(Access Token),向客户端(Client)发放了所请求的需授权资源(Protected Resource).

OAuth2.0具体来说有4种授权模式的,本文只介绍最常用到的授权码模式

授权码模式

简单来说

就是客户端在用户授权登陆后,用一个CODE换取一个访问令牌.

复杂来说


(A).客户端(Client)通过浏览器(User-Agent)把用户导向认证服务器(Authorization Server)的认证地址(Client Identifier & Redirection URI)。
(B).用户(Resource Owner)在浏览器(User-Agent)上向认证服务器(Authorization Server)上确认是否授权给客户端(User authenticates)。
(C).假设用户确认了授权,认证服务器(Authorization Server)就会把用户导向一个用户预先指定的重定向URI,并附上一个认证授权码(Authorization Code)。
(——————–后台操作,以下操作用户不可见——————– )
(D).客户端(Client)在上一步得到的认证授权码(Authorization Code),附上上一步的重定向URI(Redirection URI),向认证服务器(Authorization Server)申请一个令牌。
(E).认证服务器(Authorization Server)核实了认证授权码和重定向URI,向客户端(Client)发放访问令牌(Access Token)还有更新令牌(Refresh Token)。

下面具体来说一下实例


PYTHON实现第三方登录发微博


值得注意的是因为,获得授权码步骤需要回跳到回调地址,而python脚本并不能直接获得回调地址的code,所以需要手动填写code,故我分了2个python文件来完成这个过程。

前期准备

新浪微博第三方发微博,首先需要在微博开放平台注册一个应用,然后获取应用的App Key, App Sercet以及[应用设置]-[高级信息]中设置一个授权回调页

流程

1.拼接一个带有App Key& 授权回调页的导向授权服务器的URI给用户访问,同时指定使用的授权模式是授权码模式(respones_type=code)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: sinaweibo.py
import requests
import urllib
import json
import requests
import webbrowser

APP_KEY = '590934953'
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html'
authorize_url = 'https://api.weibo.com/oauth2/authorize?client_id='+APP_KEY+'&response_type=code&redirect_uri='+REDIRECT_URL

webbrowser.open(authorize_url , new=0, autoraise=True)

2.用户会跳到一个新浪官网提供的登录页面,用户同意授权后,页面会跳回一个带有CODE参数的授权回调页

http://[[REDIRECT_URL]]/?code=[[CODE]]

3.拼接一个带有App Key& App Sercet&授权回调页&CODE的URL,访问他并的到一个Json数据包,里面含有令牌Access Token.

4.使用获得的Access Token调用微博API来发送微博

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: index.py
import requests
import urllib
import json

'''
获得令牌
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''

# 手动获取CODE
code = raw_input('CODE:')
# APP KEY
client_id = '590934953'
# APP Secret
client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
# 授权模式
grant_type = 'authorization_code'
# 回调地址
callback = 'https://api.weibo.com/oauth2/default.html'

# 新浪微博获取令牌Access Token的API地址
url = 'https://api.weibo.com/oauth2/access_token'
# 拼接数据
post_data = {'code':code,'client_id':client_id,'client_secret':client_secret,'grant_type':grant_type,'redirect_uri':callback}
# 拼接URL
access_token_url = url+'?'+urllib.urlencode(post_data)
# 发送post请求
r = requests.post(url=access_token_url,data='NULL')
# 获得json数据结果并解析json结果
data = json.loads(r.content)
# 获得json数据中的access_token令牌
access_token = data['access_token']

'''
发送微博
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''

# 获得要发送的微博内容
status = raw_input('TEXT:')
# 发送微博API地址
update_url_tmp = 'https://api.weibo.com/2/statuses/update.json'
# 拼接post数据
update_data = {'access_token':access_token,'status':status}
# 拼接URL
update_url = update_url_tmp+'?'+urllib.urlencode(update_data)
print update_url
# POST请求URL
update = requests.post(url=update_url_tmp, data = update_data )
# 打印结果
print update.content


PHP实现第三方登录发微博

代码我就不写了,有意的可以直接联系我拿,毕竟篇幅比较长。提几个要点。

PHP可以通过处理获得回调地址中的code,所以体验上PHP更为流畅,但是因为回调地址的页面需要自己来编写,所以也需要一个服务器来放置回调页面文件。

核心

  1. 通过多次CURL来获得access_token
  2. 通过setcookies来吧access_token作为一个缓存,优化体验,已经登陆过的就不需要都要去鉴权。
  3. 我这是只是测试用,所以就假设了一个test.or2.in地址,在本地host上也添加了test.or2.in 127.0.0.1,这样就变成回调了我本地的apache服务器。


史上巨坑

我第一次运用OAuth2.0, 得知获取Access_token需要POST请求,我就把app_key, app_secret, code这些都弄成son格式放到post请求内容中,但是系统一直提示我并没有收到这些数据。

经过查阅研究后才发现,OAuth2.0只是需要一个POST请求,但是POST请求内容为空,但是数据都是以GET形式拼接在URL后面!所以小伙伴要多注意这个问题,避免重复跳坑。



参考