baidu-sdk 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +5 -0
- data/README.md +73 -20
- data/lib/baidu/oauth.rb +1 -0
- data/lib/baidu/oauth/client.rb +50 -7
- data/lib/baidu/oauth/flow/{code.rb → authorization_code.rb} +9 -12
- data/lib/baidu/oauth/flow/base.rb +18 -9
- data/lib/baidu/oauth/flow/client_credentials.rb +37 -0
- data/lib/baidu/oauth/flow/device.rb +6 -13
- data/lib/baidu/oauth/flow/implicit_grant.rb +57 -0
- data/lib/baidu/version.rb +1 -1
- data/spec/baidu/oauth/client_spec.rb +72 -19
- data/spec/fixtures/get_token_client_credentials.json +8 -0
- data/spec/fixtures/token_info.json +7 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7d739a156a7feec33727249033320452ff730d1
|
4
|
+
data.tar.gz: 1db71954fe27d31241176786cab6ec5dbd18ae09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ea790ba81dabc1968e53664a95e30b741ba1d9c282d4631edeac230b9b2c9e631d359add53badf7636e7acda6dfff7f924ccf98ceeced42b166627766d9afe7
|
7
|
+
data.tar.gz: 19e130371ed9e9d9f804b0fbf60e1e6a6e4dc5c9df7f1b50e715cd3152b404c942a1594202194a8dd1e1b775c16bf6e74d126cb55b40bbbfeeaf8e690eab4780
|
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Baidu SDK for Ruby [![Build Status](https://travis-ci.org/lonre/baidu-sdk-ruby.png?branch=master)](https://travis-ci.org/lonre/baidu-sdk-ruby)
|
2
2
|
|
3
3
|
Unofficial Baidu REST API SDK for Ruby.
|
4
|
+
|
4
5
|
非官方百度开放接口 Ruby 开发包。
|
5
6
|
|
6
7
|
## 安装
|
@@ -26,10 +27,14 @@ Unofficial Baidu REST API SDK for Ruby.
|
|
26
27
|
|
27
28
|
`Hash` 必须使用 `symbol` key,无论是返回值或作为参数传递给方法。
|
28
29
|
|
29
|
-
涉及到调用 Baidu REST API 并返回 Hash
|
30
|
+
涉及到调用 Baidu REST API 并返回 Hash 时,此 Hash 返回值是在原始 API 返回的 JSON 数据之上 `parse(JSON.parse(resp.body, symbolize_names: true))` 而来。(特别说明返回值的除外,如:`Baidu::OAuth::Flow::Code#get_token` 返回 `Baidu::Session`)。Hash 和 JSON 拥有相同的结构,返回的具体结构可以参考各个方法的 API Doc。如:
|
31
|
+
|
30
32
|
```ruby
|
31
33
|
# 返回的原始 JSON
|
32
34
|
# {"quota":15000000000,"used":5221166,"request_id":4043312634}
|
35
|
+
#
|
36
|
+
# result 是转换 JSON 后得到的 Hash
|
37
|
+
# {:quota=>15000000000, :used=>5221166, :request_id=>4043312634}
|
33
38
|
result = pcs_client.quota
|
34
39
|
result[:quota] # => 15000000000
|
35
40
|
result[:used] # => 5221166
|
@@ -39,6 +44,7 @@ result[:used] # => 5221166
|
|
39
44
|
首先确保已经在百度开发者中心创建了应用。如果还没有创建应用,请通过此链接 [百度开发者中心](http://developer.baidu.com/console) 创建一个新的应用,获取应用的 `API Key` 和 `Secret Key`。
|
40
45
|
|
41
46
|
1. 使用全局配置方式:
|
47
|
+
|
42
48
|
```ruby
|
43
49
|
Baidu.config do |c|
|
44
50
|
c.client_id = 'an_api_key'
|
@@ -48,31 +54,64 @@ result[:used] # => 5221166
|
|
48
54
|
此全局配置为可选方式,还可以在新建 `Baidu::OAuth::Client` 实例的时候指定 `API Key` 和 `Secret Key`。
|
49
55
|
|
50
56
|
2. 创建 Baidu::OAuth::Client 实例
|
57
|
+
|
58
|
+
首先,加载 `oauth` 库
|
59
|
+
|
51
60
|
```ruby
|
52
61
|
require 'baidu/oauth'
|
62
|
+
```
|
63
|
+
其次,创建实例
|
64
|
+
|
65
|
+
```ruby
|
53
66
|
client = Baidu::OAuth::Client.new
|
54
|
-
#
|
67
|
+
# 或如下,为实例指定 client_id, client_secret
|
55
68
|
client = Baidu::OAuth::Client.new('a_client_id', 'a_client_secret')
|
56
69
|
```
|
57
70
|
后者创建的实例受全局配置影响
|
58
|
-
|
71
|
+
|
72
|
+
3. Baidu OAuth 有四种获取 Access Token 的方式,包括 `Authorization Code`, `Implicit Grant`, `Client Credentials`, `Device`以及一个刷新方式`Refresh Token`
|
59
73
|
|
60
74
|
```ruby
|
61
|
-
|
62
|
-
client.
|
63
|
-
|
64
|
-
|
65
|
-
client.
|
75
|
+
# 使用 Authorization Code 授权流程,获取 Authorization URL
|
76
|
+
client.authorization_code_flow.authorize_url('callback_uri')
|
77
|
+
|
78
|
+
# 使用 Authorization Code 授权流程,获取 Access Token(Baidu::Session)
|
79
|
+
client.authorization_code_flow.get_token('code', 'callback_uri')
|
80
|
+
|
81
|
+
# 使用 Device 授权流程,获取 User Code 和 Device Code
|
82
|
+
client.device_flow.user_and_device_code
|
83
|
+
|
84
|
+
# 使用 Device 授权流程,获取 Access Token(Baidu::Session)
|
85
|
+
client.device_flow.get_token('code')
|
86
|
+
|
87
|
+
# 使用 Implicit Grant 授权流程
|
88
|
+
client.implicit_grant_flow.authorize_url('callback_uri')
|
89
|
+
|
90
|
+
# 使用 Implicit Grant 授权流程授权后,
|
91
|
+
# 客户端解析 callback_uri 中 Fragment 所携带参数获取 Access Token
|
92
|
+
# http://localhost:4567/auth/callback#expires_in=2592000&access_token=3.c79b45...
|
93
|
+
|
94
|
+
# 使用 Client Credentials 授权流程获取 Access Token
|
95
|
+
client.client_credentials_flow.get_token
|
96
|
+
|
97
|
+
# 刷新并获取新的 Access Token(Baidu::Session),所有流程均适用
|
98
|
+
client.refresh('refresh_token')
|
66
99
|
```
|
67
|
-
|
100
|
+
|
101
|
+
4. `Baidu::Session` 授权信息
|
102
|
+
|
103
|
+
所有 `get_token` 及 `refresh` 均返回 `Baidu::Session`,包含授权信息,如:
|
68
104
|
|
69
105
|
```ruby
|
70
|
-
session = client.
|
71
|
-
session
|
72
|
-
|
106
|
+
session = client.device_flow.get_token('code')
|
107
|
+
puts session.access_token
|
108
|
+
puts session.refresh_token
|
109
|
+
puts session.scope
|
110
|
+
puts session.session_key
|
111
|
+
puts session.session_secret
|
73
112
|
```
|
74
113
|
|
75
|
-
### Authorization Code
|
114
|
+
### Sinatra Authorization Code 授权简单示例
|
76
115
|
|
77
116
|
```ruby
|
78
117
|
# 1. Edit and save this snippet as code.rb
|
@@ -96,13 +135,13 @@ end
|
|
96
135
|
|
97
136
|
get '/auth' do
|
98
137
|
client = Baidu::OAuth::Client.new
|
99
|
-
redirect client.
|
138
|
+
redirect client.authorization_code_flow.authorize_url(callback_uri, confirm_login: true)
|
100
139
|
end
|
101
140
|
|
102
141
|
get '/auth/callback' do
|
103
142
|
begin
|
104
143
|
client = Baidu::OAuth::Client.new
|
105
|
-
session = client.
|
144
|
+
session = client.authorization_code_flow.get_token params[:code], callback_uri
|
106
145
|
"auth success: #{session.access_token}"
|
107
146
|
rescue => e
|
108
147
|
e.to_s
|
@@ -113,9 +152,12 @@ end
|
|
113
152
|
## PCS
|
114
153
|
要使用 PCS 必须到 [百度开发者中心](http://developer.baidu.com/console) 开启指定应用的 PCS API 权限,参考 [开通PCS API权限](http://developer.baidu.com/wiki/index.php?title=docs/pcs/guide/api_approve),并获取所设置的文件目录。
|
115
154
|
|
116
|
-
|
155
|
+
PCS 服务 API 包括文件 API 以及结构化数据 API,目前已经实现全部文件 API。
|
156
|
+
|
157
|
+
**API 中涉及到的文件或目录路径,都是相对于开通 PCS API 权限时所设置的文件目录**。比如:上传文件时需要指定文件保存路径,假设指定为 `/mydata/hi.png`,那么在 PCS 中实际的保存路径为 `/apps/文件目录/mydata/hi.png`。
|
117
158
|
|
118
159
|
1. 全局配置
|
160
|
+
|
119
161
|
```ruby
|
120
162
|
Baidu.config do |c|
|
121
163
|
# ...
|
@@ -126,14 +168,22 @@ end
|
|
126
168
|
全局配置非强制性的,可以在创建 `Baidu::PCS::Client` 实例时设置
|
127
169
|
|
128
170
|
2. 创建 Baidu::PCS::Client 实例
|
171
|
+
|
172
|
+
首先,加载 `pcs` 库
|
173
|
+
|
129
174
|
```ruby
|
130
175
|
require 'baidu/pcs'
|
176
|
+
```
|
177
|
+
其次,创建实例
|
178
|
+
|
179
|
+
```ruby
|
131
180
|
client = Baidu::PCS::Client.new('token_or_session')
|
132
|
-
#
|
181
|
+
# 或如下,为实例指定文件目录
|
133
182
|
client = Baidu::PCS::Client.new('token_or_session', 'notes')
|
134
183
|
```
|
135
184
|
|
136
185
|
3. API 调用
|
186
|
+
|
137
187
|
```ruby
|
138
188
|
File.open('/opt/ubuntu-12.04.3-server-amd64.iso', 'r') do |f|
|
139
189
|
client.upload(f, block_upload: true)
|
@@ -143,11 +193,14 @@ end
|
|
143
193
|
## 异常处理
|
144
194
|
API 的异常被封装为 `Baidu::Errors::Error`,包含三个子类:
|
145
195
|
|
146
|
-
|
147
|
-
|
148
|
-
|
196
|
+
```
|
197
|
+
1. Baidu::Errors::AuthError # 未授权或 Access Token 过期
|
198
|
+
2. Baidu::Errors::ClientError # API 返回 400+ 错误
|
199
|
+
3. Baidu::Errors::ServerError # API 返回 500+ 错误
|
200
|
+
```
|
149
201
|
|
150
202
|
`Baidu::Errors::Error => e`,异常的具体信息可以通过如下方式获取到:
|
203
|
+
|
151
204
|
```ruby
|
152
205
|
begin
|
153
206
|
client.list('apitest/movies')
|
data/lib/baidu/oauth.rb
CHANGED
data/lib/baidu/oauth/client.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require 'baidu/oauth/flow/
|
3
|
+
require 'baidu/oauth/flow/authorization_code'
|
4
4
|
require 'baidu/oauth/flow/device'
|
5
|
+
require 'baidu/oauth/flow/implicit_grant'
|
6
|
+
require 'baidu/oauth/flow/client_credentials'
|
5
7
|
|
6
8
|
module Baidu
|
7
9
|
module OAuth
|
@@ -27,17 +29,30 @@ module Baidu
|
|
27
29
|
@site = Baidu::OAuth::SITE
|
28
30
|
end
|
29
31
|
|
30
|
-
# @!method
|
32
|
+
# @!method authorization_code_flow
|
31
33
|
# 采用 Authorization Code 获取 Access Token 的授权验证流程
|
32
|
-
# @return [Flow::
|
34
|
+
# @return [Flow::AuthorizationCode]
|
35
|
+
#
|
33
36
|
# @!method device_flow
|
34
37
|
# 采用 Device Code 获取 Access Token 的授权验证流程
|
35
38
|
# @return [Flow::Device]
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
39
|
+
#
|
40
|
+
# @!method implicit_grant_flow
|
41
|
+
# 采用 Implicit Grant 方式获取 Access Token 的授权验证流程
|
42
|
+
# @return [Flow::ImplicitGrant]
|
43
|
+
#
|
44
|
+
# @!method client_credentials_flow
|
45
|
+
# 使用 Client Credentials 获取 Access Token 的授权验证流程
|
46
|
+
# @return [Flow::ClientCredentials]
|
47
|
+
#
|
48
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization Authorization Code 授权
|
49
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device Device 授权
|
50
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/implicit Implicit Grant 授权
|
51
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/client Client Credentials 授权
|
52
|
+
[:authorization_code, :device, :implicit_grant, :client_credentials].each do |flow|
|
39
53
|
define_method("#{flow}_flow".to_sym) do
|
40
|
-
|
54
|
+
klass_name = flow.to_s.split('_').map { |s| s.capitalize }.join
|
55
|
+
Baidu::OAuth::Flow.const_get(klass_name).new self
|
41
56
|
end
|
42
57
|
end
|
43
58
|
|
@@ -61,6 +76,34 @@ module Baidu
|
|
61
76
|
return nil if rest.nil?
|
62
77
|
Baidu::Session.from rest
|
63
78
|
end
|
79
|
+
|
80
|
+
# 查询Access Token对应的授权信息
|
81
|
+
#
|
82
|
+
# 该接口用于查询Access Token对应的授权相关信息,
|
83
|
+
# 包括授权对象(应用)、授权用户、授权的权限、授权时间,过期时间。
|
84
|
+
# @example 返回的原始 JSON
|
85
|
+
# {
|
86
|
+
# "client_id": "ZLycGmiUcCkrSb3t7zSD8uV6",
|
87
|
+
# "userid": 689911016,
|
88
|
+
# "scope": "basic super_msg",
|
89
|
+
# "create_time": 1364555477,
|
90
|
+
# "expire_in": 2591980
|
91
|
+
# }
|
92
|
+
#
|
93
|
+
# :client_id Access Token对应应用的Api Key
|
94
|
+
# :userid 授权用户的唯一id。如果Access Token是通过Client Credentials授权方式 获取的,则该字段值为0
|
95
|
+
# :scope Access Token最终的访问范围,即用户实际授予的权限列表(用户在授权页面时,有可能会取消掉某些请求的权限)
|
96
|
+
# :create_time Access Token的生成时间(Unix时间戳),以秒为单位
|
97
|
+
# :expires_in Access Token剩余的有效时间,以秒为单位
|
98
|
+
#
|
99
|
+
# @param [String] access_token 授权之后应用得到的Access Token
|
100
|
+
# @return [Hash]
|
101
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/tokeninfo 校验Access Token
|
102
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/list 权限列表
|
103
|
+
def token_info(access_token)
|
104
|
+
body = { access_token: access_token }
|
105
|
+
return post Baidu::OAuth::TOKEN_INFO_ENDPOINT, nil, body
|
106
|
+
end
|
64
107
|
end
|
65
108
|
end
|
66
109
|
end
|
@@ -10,20 +10,21 @@ module Baidu
|
|
10
10
|
# 适用于所有有Server端的应用,如Web/Wap站点、有Server端的手机/桌面客户端应用等。
|
11
11
|
#
|
12
12
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization Authorization Code授权
|
13
|
-
class
|
14
|
-
include
|
13
|
+
class AuthorizationCode < Base
|
14
|
+
include Authable
|
15
|
+
include Tokenable
|
15
16
|
|
16
|
-
#
|
17
|
+
# 通过获得的 Authorization Code,换取一个 Access Token
|
17
18
|
#
|
18
19
|
# @note 每一个 Authorization Code 的有效期为10分钟,并且只能使用一次,再次使用将无效。
|
19
20
|
#
|
20
21
|
# 如果用户在此页面同意授权,授权服务则将重定向用户浏览器到应用所指定的“redirect_uri”,
|
21
22
|
# 并附带上表示授权服务所分配的 Authorization Code 的 +code+ 参数,以及 state 参数(如果请求authorization code时带了这个参数)。
|
22
23
|
#
|
23
|
-
# @param [String] code 所获得的 Authorization Code (redirect_uri 附带的
|
24
|
+
# @param [String] code 所获得的 Authorization Code (redirect_uri 附带的 code 参数)
|
25
|
+
# @param [String] redirect_uri 该值必须与获取 Authorization Code 时传递的 “redirect_uri” 保持一致
|
24
26
|
# @return [Baidu::Session]
|
25
|
-
# @see
|
26
|
-
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device 通过Device Code获取Access Token
|
27
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization Authorization Code授权
|
27
28
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/overview Access Token生命周期
|
28
29
|
def get_token(code, redirect_uri); super end
|
29
30
|
|
@@ -44,15 +45,11 @@ module Baidu
|
|
44
45
|
# @option params [Boolean] :force_login +true+ 表示加载登录页时强制用户输入用户名和口令,不会从cookie中读取百度用户的登陆状态
|
45
46
|
# @option params [Boolean] :confirm_login +true+ 表示且百度用户已处于登陆状态,会提示是否使用已当前登陆用户对应用授权
|
46
47
|
# @return [String]
|
48
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization Authorization Code授权
|
47
49
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/list 权限列表
|
48
50
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/set 页面设置
|
49
51
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/redirect 授权回调地址
|
50
|
-
def authorize_url(redirect_uri, params={})
|
51
|
-
opts = {}.update(params)
|
52
|
-
opts.update({ force_login: 1 }) if params[:force_login]
|
53
|
-
opts.update({ confirm_login: 1 }) if params[:confirm_login]
|
54
|
-
super redirect_uri, opts
|
55
|
-
end
|
52
|
+
def authorize_url(redirect_uri, params={}); super end
|
56
53
|
|
57
54
|
private
|
58
55
|
|
@@ -3,26 +3,41 @@
|
|
3
3
|
module Baidu
|
4
4
|
module OAuth
|
5
5
|
module Flow
|
6
|
-
|
7
|
-
|
6
|
+
|
7
|
+
# 所有授权流程基类
|
8
|
+
class Base
|
8
9
|
|
9
10
|
# 此授权流程对应的 OAuth Client 实例
|
11
|
+
# @return [Baidu::OAuth::Client]
|
10
12
|
attr_reader :client
|
11
13
|
|
12
14
|
def initialize(client)
|
13
15
|
@client = client
|
14
16
|
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @private
|
20
|
+
module Authable
|
21
|
+
include Baidu::Support
|
15
22
|
|
23
|
+
# Sub class must implement +authorize_query+ method
|
16
24
|
def authorize_url(redirect_uri, params={})
|
17
25
|
query = authorize_query.update params
|
18
26
|
query.update({ client_id: self.client.client_id, redirect_uri: redirect_uri })
|
27
|
+
query.update({ force_login: 1 }) if params[:force_login]
|
28
|
+
query.update({ confirm_login: 1 }) if params[:confirm_login]
|
19
29
|
Util.clean_params query
|
20
30
|
uri = URI(self.client.site)
|
21
|
-
uri.path =
|
31
|
+
uri.path = Baidu::OAuth::AUTHORIZATION_ENDPOINT
|
22
32
|
uri.query = Util.encode_params(query) unless Util.blank? query
|
23
33
|
uri.to_s
|
24
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @private
|
38
|
+
module Tokenable
|
25
39
|
|
40
|
+
# Sub class must implement +token_body+ method
|
26
41
|
def get_token(code, redirect_uri=nil, params={})
|
27
42
|
body = token_body.update params
|
28
43
|
body.update({ client_id: self.client.client_id,
|
@@ -32,12 +47,6 @@ module Baidu
|
|
32
47
|
return nil if rest.nil?
|
33
48
|
Baidu::Session.from rest
|
34
49
|
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def authorize_endpoint
|
39
|
-
Baidu::OAuth::AUTHORIZATION_ENDPOINT
|
40
|
-
end
|
41
50
|
end
|
42
51
|
end
|
43
52
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'baidu/oauth/flow/base'
|
4
|
+
|
5
|
+
module Baidu
|
6
|
+
module OAuth
|
7
|
+
module Flow
|
8
|
+
|
9
|
+
# 采用Client Credentials方式,即应用公钥、密钥方式获取Access Token,
|
10
|
+
# 适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open API,
|
11
|
+
# 并且需要开发者提前向百度开放平台申请,成功对接后方能使用。
|
12
|
+
# 对于应用而言,其流程只有一步,即直接获取Access Token。
|
13
|
+
#
|
14
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/client Client Credentials授权
|
15
|
+
class ClientCredentials < Base
|
16
|
+
include Tokenable
|
17
|
+
|
18
|
+
# 使用 Client Credentials 获取 Access Token
|
19
|
+
#
|
20
|
+
# @param [String] scope Access Token最终的访问范围,即用户实际授予的权限列表
|
21
|
+
# @return [Baidu::Session]
|
22
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/client Client Credentials授权
|
23
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/list 权限列表
|
24
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/overview Access Token生命周期
|
25
|
+
def get_token(scope=nil)
|
26
|
+
super(nil, nil, scope: scope)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def token_body
|
32
|
+
{ grant_type: 'client_credentials' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -10,9 +10,10 @@ module Baidu
|
|
10
10
|
# 填写User Code并授权、以及通过Device Code获取Access Token这3步组成。
|
11
11
|
#
|
12
12
|
# @note 使用此授权流程,对于终端类型的应用也非常方便,同时还可以获取 Refresh Token
|
13
|
+
#
|
13
14
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device Device授权
|
14
|
-
class Device
|
15
|
-
include
|
15
|
+
class Device < Base
|
16
|
+
include Tokenable
|
16
17
|
|
17
18
|
# 获取 User Code 和 Device Code
|
18
19
|
# @example 返回的原始 JSON
|
@@ -35,11 +36,12 @@ module Baidu
|
|
35
36
|
#
|
36
37
|
# @param [String] scope 非必须参数,以空格分隔的权限列表
|
37
38
|
# @return [Hash]
|
39
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device Device授权
|
38
40
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/list 权限列表
|
39
41
|
def user_and_device_code(scope=nil)
|
40
42
|
query = authorize_query.update({ client_id: self.client.client_id })
|
41
43
|
query[:scope] = scope unless scope.nil?
|
42
|
-
self.client.get(
|
44
|
+
self.client.get(Baidu::OAuth::DEVICE_ENDPOINT, query)
|
43
45
|
end
|
44
46
|
|
45
47
|
# 通过 Device Code 来获取 Access Token
|
@@ -47,15 +49,10 @@ module Baidu
|
|
47
49
|
# @param [String] code {#user_and_device_code} 所获得的 Device Code
|
48
50
|
# @return [Baidu::Session]
|
49
51
|
# @see #user_and_device_code
|
50
|
-
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device
|
52
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/device Device授权
|
51
53
|
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/overview Access Token生命周期
|
52
54
|
def get_token(code); super end
|
53
55
|
|
54
|
-
# @private
|
55
|
-
def authorize_url
|
56
|
-
raise NoMethodError, 'no such method in device flow'
|
57
|
-
end
|
58
|
-
|
59
56
|
private
|
60
57
|
|
61
58
|
def authorize_query
|
@@ -65,10 +62,6 @@ module Baidu
|
|
65
62
|
def token_body
|
66
63
|
{ grant_type: 'device_token' }
|
67
64
|
end
|
68
|
-
|
69
|
-
def authorize_endpoint
|
70
|
-
Baidu::OAuth::DEVICE_ENDPOINT
|
71
|
-
end
|
72
65
|
end
|
73
66
|
end
|
74
67
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'baidu/oauth/flow/base'
|
4
|
+
|
5
|
+
module Baidu
|
6
|
+
module OAuth
|
7
|
+
module Flow
|
8
|
+
|
9
|
+
# 采用Implicit Grant方式获取Access Token的授权验证流程又被称为User-Agent Flow,
|
10
|
+
# 适用于所有无Server端配合的应用(由于应用往往位于一个User Agent里,如浏览器里面,
|
11
|
+
# 因此这类应用在某些平台下又被称为Client-Side Application),如手机/桌面客户端程序、浏览器插件等,
|
12
|
+
# 以及基于JavaScript等脚本客户端脚本语言实现的应用,他们的一个共同特点是,
|
13
|
+
# 应用无法妥善保管其应用密钥(App Secret Key)
|
14
|
+
#
|
15
|
+
# @note 采用Implicit Grant方式获取Access Token时,不会返回Refresh Token。
|
16
|
+
# @note
|
17
|
+
# 为了保证安全性,建议应用从授权回调地址接收到Access Token之后,
|
18
|
+
# 调用Access Token验证接口判断该Access Token是否对应自身的Api Key。
|
19
|
+
#
|
20
|
+
# @see Client#token_info
|
21
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/implicit Implicit Grant授权
|
22
|
+
class ImplicitGrant < Base
|
23
|
+
include Authable
|
24
|
+
|
25
|
+
# 获取 Authorization URL
|
26
|
+
#
|
27
|
+
# @note
|
28
|
+
# 为了加强安全性,会对跳转到该授权页面的Referer进行检测,
|
29
|
+
# 要求Referer必须与开发者创建应用时注册的"网站地址"或者在“OAuth安全设置”中所填写的"根域名绑定"同域。
|
30
|
+
#
|
31
|
+
# @param [String] redirect_uri
|
32
|
+
# 授权后要回调的URI,即接受Access Token的URI。
|
33
|
+
# 如果用户在授权过程中取消授权,会回调该URI,并在URI末尾附上error=access_denied参数。
|
34
|
+
# 对于无Web Server的应用,其值可以是“oob”,授权后会回调OAuth提供的一个默认页面。
|
35
|
+
# 如果redirect_uri不为"oob",则redirect_uri指向的页面必须与开发者在“OAuth安全设置”中所填写的"授权回调地址"相匹配。
|
36
|
+
# @option params [String] :scope 以空格分隔的权限列表,若不传递此参数,代表请求用户的默认权限
|
37
|
+
# @option params [String] :state
|
38
|
+
# 用于保持请求和回调的状态,授权服务器在回调时(重定向用户浏览器到“redirect_uri”时),会在Fragment中原样回传该参数。
|
39
|
+
# @option params [String] :display 登录和授权页面的展现样式,默认为“page”
|
40
|
+
# @option params [Boolean] :force_login +true+ 表示加载登录页时强制用户输入用户名和口令,不会从cookie中读取百度用户的登陆状态
|
41
|
+
# @option params [Boolean] :confirm_login +true+ 表示且百度用户已处于登陆状态,会提示是否使用已当前登陆用户对应用授权
|
42
|
+
# @return [String]
|
43
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/implicit Implicit Grant授权
|
44
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/list 权限列表
|
45
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/set 页面设置
|
46
|
+
# @see http://developer.baidu.com/wiki/index.php?title=docs/oauth/redirect 授权回调地址
|
47
|
+
def authorize_url(redirect_uri, params={}); super end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def authorize_query
|
52
|
+
{ response_type: 'token', display: 'page' }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/baidu/version.rb
CHANGED
@@ -44,25 +44,38 @@ describe Baidu::OAuth::Client do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
context '#authorize_url' do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
context 'with code flow' do
|
48
|
+
it 'generates "Authorization Code" authorize url' do
|
49
|
+
url = @client.authorization_code_flow.authorize_url('oob')
|
50
|
+
expect(url).to eq("#{authorization_endpoint}?response_type=code&display=page&" \
|
51
|
+
"client_id=ci&redirect_uri=oob")
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
it 'generates "Authorization Code" authorize url with params' do
|
55
|
+
url = @client.authorization_code_flow.authorize_url('http://www.example.com/oauth_redirect',
|
56
|
+
scope: 'email', state: 'xyz', display: 'tv',
|
57
|
+
force_login: true, confirm_login: true)
|
58
|
+
expect(url).to eq("#{authorization_endpoint}?response_type=code&display=tv&" \
|
59
|
+
"scope=email&state=xyz&force_login=1&confirm_login=1&client_id=ci&" \
|
60
|
+
"redirect_uri=http%3A%2F%2Fwww.example.com%2Foauth_redirect")
|
61
|
+
end
|
60
62
|
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
@client.
|
65
|
-
|
64
|
+
context 'with implicit flow' do
|
65
|
+
it 'generates "Implicit Grant" authorize url' do
|
66
|
+
url = @client.implicit_grant_flow.authorize_url('oob')
|
67
|
+
expect(url).to eq("#{authorization_endpoint}?response_type=token&display=page&" \
|
68
|
+
"client_id=ci&redirect_uri=oob")
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'generates "Implicit Grant" authorize url with params' do
|
72
|
+
url = @client.implicit_grant_flow.authorize_url('http://www.example.com/oauth_redirect',
|
73
|
+
scope: 'basic email', state: 'xyz', display: 'mobile',
|
74
|
+
force_login: true, confirm_login: true)
|
75
|
+
expect(url).to eq("#{authorization_endpoint}?response_type=token&display=mobile&" \
|
76
|
+
"scope=basic+email&state=xyz&force_login=1&confirm_login=1&client_id=ci&" \
|
77
|
+
"redirect_uri=http%3A%2F%2Fwww.example.com%2Foauth_redirect")
|
78
|
+
end
|
66
79
|
end
|
67
80
|
end
|
68
81
|
|
@@ -112,7 +125,7 @@ describe Baidu::OAuth::Client do
|
|
112
125
|
end
|
113
126
|
|
114
127
|
it 'requests access tokey' do
|
115
|
-
@client.
|
128
|
+
@client.authorization_code_flow.get_token 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
|
116
129
|
'http://www.example.com/oauth_redirect'
|
117
130
|
a_post(:oauth, '/oauth/2.0/token',
|
118
131
|
grant_type: 'authorization_code',
|
@@ -122,7 +135,7 @@ describe Baidu::OAuth::Client do
|
|
122
135
|
end
|
123
136
|
|
124
137
|
it 'responses access token' do
|
125
|
-
result = @client.
|
138
|
+
result = @client.authorization_code_flow.get_token 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
|
126
139
|
'http://www.example.com/oauth_redirect'
|
127
140
|
expect(result).to be_instance_of(Baidu::Session)
|
128
141
|
expect(result).to respond_to(:access_token)
|
@@ -140,7 +153,7 @@ describe Baidu::OAuth::Client do
|
|
140
153
|
to_return(status: 200, body: ft('get_token_device.json'))
|
141
154
|
end
|
142
155
|
|
143
|
-
it 'requests access
|
156
|
+
it 'requests access token' do
|
144
157
|
@client.device_flow.get_token 'a82hjs723h72h3a82hjs723h72h3vb'
|
145
158
|
a_post(:oauth, '/oauth/2.0/token', grant_type: 'device_token',
|
146
159
|
code: 'a82hjs723h72h3a82hjs723h72h3vb',
|
@@ -159,6 +172,36 @@ describe Baidu::OAuth::Client do
|
|
159
172
|
end
|
160
173
|
end
|
161
174
|
|
175
|
+
context 'with client credentials' do
|
176
|
+
let(:base_params) do
|
177
|
+
{ grant_type: 'client_credentials', client_id: 'ci', client_secret: 'cs' }
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'requests access token' do
|
181
|
+
stub = stub_post(:oauth, '/oauth/2.0/token', base_params)
|
182
|
+
@client.client_credentials_flow.get_token
|
183
|
+
stub.should have_been_requested
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'requests access token with scope' do
|
187
|
+
stub = stub_post(:oauth, '/oauth/2.0/token', base_params.update({ scope: 'basic hao123' }))
|
188
|
+
@client.client_credentials_flow.get_token('basic hao123')
|
189
|
+
stub.should have_been_requested
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'responses access token' do
|
193
|
+
stub = stub_post(:oauth, '/oauth/2.0/token', base_params).
|
194
|
+
to_return(status: 200, body: ft('get_token_client_credentials.json'))
|
195
|
+
result = @client.client_credentials_flow.get_token
|
196
|
+
expect(result).to be_instance_of(Baidu::Session)
|
197
|
+
expect(result).to respond_to(:access_token)
|
198
|
+
expect(result).to respond_to(:refresh_token)
|
199
|
+
expect(result).to respond_to(:scope)
|
200
|
+
expect(result).to respond_to(:session_key)
|
201
|
+
expect(result).to respond_to(:session_secret)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
162
205
|
context '#refresh_token' do
|
163
206
|
before do
|
164
207
|
stub_post(:oauth, '/oauth/2.0/token', grant_type: 'refresh_token',
|
@@ -196,4 +239,14 @@ describe Baidu::OAuth::Client do
|
|
196
239
|
expect(result).to respond_to(:session_secret)
|
197
240
|
end
|
198
241
|
end
|
242
|
+
|
243
|
+
context '#token_info' do
|
244
|
+
it 'requests token info' do
|
245
|
+
stub = stub_post(:oauth, '/oauth/2.0/tokeninfo', access_token: 'xxxx').
|
246
|
+
to_return(status: 200, body: ft('token_info.json'))
|
247
|
+
rest = @client.token_info('xxxx')
|
248
|
+
stub.should have_been_requested
|
249
|
+
expect(rest).to be_instance_of(Hash)
|
250
|
+
end
|
251
|
+
end
|
199
252
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
{
|
2
|
+
"access_token": "1.a6b7dbd428f731035f771b8d15063f61.86400.1292922000-2346678-124328",
|
3
|
+
"expires_in": 86400,
|
4
|
+
"refresh_token": "2.385d55f8615fdfd9edb7c4b5ebdc3e39.604800.1293440400-2346678-124328",
|
5
|
+
"scope": "public",
|
6
|
+
"session_key": "ANXxSNjwQDugf8615OnqeikRMu2bKaXCdlLxn",
|
7
|
+
"session_secret": "248APxvxjCZ0VEC43EYrvxqaK4oZExMB"
|
8
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: baidu-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lonre Wang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multipart-post
|
@@ -61,9 +61,11 @@ files:
|
|
61
61
|
- lib/baidu/errors/error.rb
|
62
62
|
- lib/baidu/oauth.rb
|
63
63
|
- lib/baidu/oauth/client.rb
|
64
|
+
- lib/baidu/oauth/flow/authorization_code.rb
|
64
65
|
- lib/baidu/oauth/flow/base.rb
|
65
|
-
- lib/baidu/oauth/flow/
|
66
|
+
- lib/baidu/oauth/flow/client_credentials.rb
|
66
67
|
- lib/baidu/oauth/flow/device.rb
|
68
|
+
- lib/baidu/oauth/flow/implicit_grant.rb
|
67
69
|
- lib/baidu/pcs.rb
|
68
70
|
- lib/baidu/pcs/client.rb
|
69
71
|
- lib/baidu/session.rb
|
@@ -83,6 +85,7 @@ files:
|
|
83
85
|
- spec/fixtures/delete.json
|
84
86
|
- spec/fixtures/diff.json
|
85
87
|
- spec/fixtures/empty.json
|
88
|
+
- spec/fixtures/get_token_client_credentials.json
|
86
89
|
- spec/fixtures/get_token_code.json
|
87
90
|
- spec/fixtures/get_token_device.json
|
88
91
|
- spec/fixtures/list.json
|
@@ -102,6 +105,7 @@ files:
|
|
102
105
|
- spec/fixtures/search.json
|
103
106
|
- spec/fixtures/stream_list.json
|
104
107
|
- spec/fixtures/streaming.m3u8
|
108
|
+
- spec/fixtures/token_info.json
|
105
109
|
- spec/fixtures/upload.json
|
106
110
|
- spec/fixtures/upload_block.json
|
107
111
|
- spec/fixtures/user_and_device_code.json
|
@@ -143,6 +147,7 @@ test_files:
|
|
143
147
|
- spec/fixtures/delete.json
|
144
148
|
- spec/fixtures/diff.json
|
145
149
|
- spec/fixtures/empty.json
|
150
|
+
- spec/fixtures/get_token_client_credentials.json
|
146
151
|
- spec/fixtures/get_token_code.json
|
147
152
|
- spec/fixtures/get_token_device.json
|
148
153
|
- spec/fixtures/list.json
|
@@ -162,6 +167,7 @@ test_files:
|
|
162
167
|
- spec/fixtures/search.json
|
163
168
|
- spec/fixtures/stream_list.json
|
164
169
|
- spec/fixtures/streaming.m3u8
|
170
|
+
- spec/fixtures/token_info.json
|
165
171
|
- spec/fixtures/upload.json
|
166
172
|
- spec/fixtures/upload_block.json
|
167
173
|
- spec/fixtures/user_and_device_code.json
|