yol_sso 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 061fba38ddccfb3737e87608089ff75e37b7b0288e0b34b150b6011b2dfbbf40
4
+ data.tar.gz: 36924d8292b0d51261fb5d71800c3a1fc4790f57f65f297e85c0ac4274337ee6
5
+ SHA512:
6
+ metadata.gz: 4aa0e69e03cf2a4951b73b5019234ea9f3cf455879582ef4f122c6c87f30e2860b7143f3fa9e3e49ebf6aefaaafafc0f12dd3e69d157d2c0a2a4d26630ff02d7
7
+ data.tar.gz: 9f5bf41f3f012d059af1c7dc64f19de2a56fc9fcaef5ac4c612478781140514a46f797953ccc90afb27bfd241289f0315cefa154bc4634e92dd3bc01f397f8f9
data/.DS_Store ADDED
Binary file
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in yol_qy_weixin.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ yol_sso (0.0.1)
5
+ multi_xml
6
+ nokogiri
7
+ roxml
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (6.0.3.2)
13
+ concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ i18n (>= 0.7, < 2)
15
+ minitest (~> 5.1)
16
+ tzinfo (~> 1.1)
17
+ zeitwerk (~> 2.2, >= 2.2.2)
18
+ concurrent-ruby (1.1.9)
19
+ i18n (1.8.10)
20
+ concurrent-ruby (~> 1.0)
21
+ minitest (5.14.4)
22
+ multi_xml (0.6.0)
23
+ nokogiri (1.11.7-x86_64-darwin)
24
+ racc (~> 1.4)
25
+ racc (1.5.2)
26
+ rake (13.0.1)
27
+ roxml (4.1.1)
28
+ activesupport (>= 4.0)
29
+ nokogiri (>= 1.3.3)
30
+ thread_safe (0.3.6)
31
+ tzinfo (1.2.9)
32
+ thread_safe (~> 0.1)
33
+ zeitwerk (2.4.0)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler
40
+ rake
41
+ yol_sso!
42
+
43
+ BUNDLED WITH
44
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,371 @@
1
+ # Sso
2
+
3
+ This project rocks and uses MIT-LICENSE.
4
+
5
+ https://rubygems.org/gems/yol_qy_weixin
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/yol_qy_weixin.svg)](http://badge.fury.io/rb/yol_qy_weixin)
8
+
9
+ **有问题请及时提issue**
10
+
11
+ ```ruby
12
+ gem "yol_qy_weixin", git: "https://github.com/luojie2019/yol_qy_weixin.git"
13
+ ```
14
+
15
+ # 配置
16
+
17
+ ## 安装依赖Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'yol_qy_weixin'
23
+ ```
24
+ ## 配置 corpid secret
25
+
26
+ ```ruby
27
+ # 目录
28
+
29
+ file: your_project/config/qy_weixin.yml
30
+
31
+ .your_project/
32
+ ├── app
33
+ ├── bin
34
+ ├── config
35
+ │ ├── redis.yml
36
+ │ ├── database.yml
37
+ │ ├── qy_weixin.yml
38
+ ```
39
+
40
+ ```yml
41
+ defaults: &defaults
42
+ corpid: '1**'
43
+ secret: '2**'
44
+
45
+ development: &development
46
+ <<: *defaults
47
+
48
+ test:
49
+ <<: *defaults
50
+
51
+ production:
52
+ corpid: <%= ENV.fetch('QY_WEIXIN_CORPID') { '1**'' } %>
53
+ secret: <%= ENV.fetch('QY_WEIXIN_SECRET') { '2**'' } %>
54
+ ```
55
+
56
+ **说明:考虑access_token需要缓存,redis配置请参考官方文档 https://github.com/redis/redis-rb/blob/master/README.md**
57
+
58
+ ## 读取配置
59
+ ```ruby
60
+ # 读取qy_weixin.yml配置
61
+ qy_weixin_config = YAML::load(ERB.new(File.read("#{Rails.root}/config/qy_weixin.yml")).result)[Rails.env]
62
+ ```
63
+ 如果你是在Rails框架下,也可以使用Settingslogic读取yml配置:
64
+ ```ruby
65
+ # 引用gem
66
+ gem 'settingslogic', '2.0.9'
67
+
68
+ # your_project/app/settings/weixin_setting.rb
69
+ class WeixinSetting < Settingslogic
70
+ source "#{Rails.root}/config/weixin.yml"
71
+ namespace Rails.env
72
+ end
73
+
74
+ corpid = WeixinSetting.corpid
75
+ corp_secret = WeixinSetting.secret
76
+ ```
77
+
78
+ ## 实例对象
79
+
80
+ ```ruby
81
+ # 目录 file: your_project/config/initializers/qy_weixin.rb
82
+
83
+ QyWexinClient = YolQyWeixin::Client.new(
84
+ corpid: qy_weixin_config["corpid"],
85
+ secret: qy_weixin_config["secret"],
86
+ redis: RedisClient
87
+ )
88
+ ```
89
+
90
+ **说明:RedisClient为redis实例,如果没有配置可传nil,建议使用redis,考虑到access_token获取次数限制;**
91
+
92
+ # 基本用法
93
+
94
+ 如果需要获取的 access_token
95
+
96
+ ```ruby
97
+ access_token = QyWexinClient.get_access_token
98
+ # 返回参考企业微信官方文档:https://work.weixin.qq.com/api/doc/90000/90135/91039
99
+ ```
100
+
101
+ ## 部门
102
+
103
+ ```ruby
104
+ 待补充,有需要可提issue到git:https://github.com/luojie2019/yol_qy_weixin.git
105
+ ```
106
+
107
+ ## 成员
108
+
109
+ ```ruby
110
+ # 获取成员信息
111
+ access_token = QyWexinClient.get_user_info(open_id)
112
+ # 返回参考企业微信官方文档:https://open.work.weixin.qq.com/api/doc/90000/90135/90196
113
+
114
+ # 获取反问用户信息
115
+ access_token = QyWexinClient.get_user_id(code)
116
+ # 返回参考企业微信官方文档:https://open.work.weixin.qq.com/api/doc/90000/90135/91707
117
+ ```
118
+
119
+
120
+ ---
121
+
122
+
123
+ 后续功能实现还待优化,有需要可提issue到git:https://github.com/luojie2019/yol_qy_weixin.git
124
+
125
+ ## 标签
126
+
127
+ ```ruby
128
+ group_client.tag.create(name)
129
+ group_client.tag.update(id, name)
130
+ group_client.tag.delete(id)
131
+ group_client.tag.get(id)
132
+ group_client.tag.add_tag_users(id, user_ids)
133
+ group_client.tag.delete_tag_users(id, user_ids)
134
+ group_client.tag.list
135
+ ```
136
+
137
+ ## 自定义菜单
138
+
139
+ menu_json的生成方法请参考:
140
+ https://github.com/lanrion/weixin_rails_middleware/wiki/DIY-menu
141
+
142
+ ```ruby
143
+ group_client.menu.create(menu_json, app_id)
144
+ group_client.menu.delete(app_id)
145
+ group_client.menu.get(app_id)
146
+ ```
147
+
148
+ ## Oauth2用法
149
+
150
+ 先要配置你应用的 可信域名 `2458023e.ngrok.com`
151
+ state 为开发者自定义参数,可选
152
+
153
+ ```ruby
154
+ # 生成授权url
155
+ group_client.oauth.authorize_url("http://2458023e.ngrok.com", "state")
156
+
157
+ # 获取code后,获取用户信息
158
+ # app_id: 跳转链接时所在的企业应用ID
159
+ group_client.oauth.get_user_info("code", "app_id")
160
+ ```
161
+
162
+ ## 发送消息
163
+
164
+ ```ruby
165
+ # params: (users, parties, tags, agent_id, content, safe=0)
166
+ # users, parties, tags 如果是多个用户,传数组,如果是全部,则直接传 "@all"
167
+ group_client.message.send_text("@all", "@all", "@all", app_id, text_message)
168
+ ```
169
+ **其他发送消息方法请查看 api/message.rb**
170
+
171
+ ## 上传多媒体文件
172
+ ```ruby
173
+ # params: media, media_type
174
+ group_client.media.upload(image_jpg_file, "image")
175
+
176
+ # 获取下载链接
177
+ # 返回一个URL,请开发者自行使用此url下载
178
+ group_client.media.get_media_by_id(media_id)
179
+
180
+ # 上传永久图文素材
181
+ # articles 为图文列表:
182
+ {
183
+ "title": "Title01",
184
+ "thumb_media_id": "2-G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0",
185
+ "author": "zs",
186
+ "content_source_url": "",
187
+ "content": "Content001",
188
+ "digest": "airticle01",
189
+ "show_cover_pic": "0"
190
+ }
191
+ group_client.material.add_mpnews(agent_id, articles)
192
+
193
+ # 更新图文素材
194
+ group_client.material.update_mpnews(agent_id, media_id, articles=[])
195
+
196
+ # 上传其他类型永久素材
197
+ # type: "image", "voice", "video", "file"
198
+ # file: File
199
+ group_client.material.add_material(agent_id, type, file)
200
+
201
+ # 删除永久素材
202
+ group_client.material.del(agent_id, media_id)
203
+
204
+ # 获取素材总数
205
+ group_client.material.get_count(agent_id)
206
+
207
+ # 获取素材列表
208
+ group_client.material.list(agent_id, type, offset, count=20)
209
+ ```
210
+
211
+ ## 第三方应用
212
+
213
+ 这里特别注意:保留 suite_access_token的cache是直接利用了前文配置的cache_store缓存。
214
+
215
+ ### api 使用介绍
216
+
217
+ ```ruby
218
+ suite_api = QyWechatApi::Suite.service(suite_id, suite_secret, suite_ticket)
219
+
220
+ # 获取预授权码
221
+ suite_api.get_pre_auth_code(appid=[])
222
+
223
+ # 获取企业号的永久授权码
224
+ suite_api.get_permanent_code(auth_code)
225
+
226
+ # 获取企业号的授权信息
227
+ suite_api.get_auth_info(auth_corpid, code)
228
+
229
+ # 获取企业号应用
230
+ suite_api.get_agent(auth_corpid, code, agent_id)
231
+
232
+ # 设置授权方的企业应用的选项设置信息
233
+ suite_api.set_agent(auth_corpid, permanent_code, agent_info)
234
+
235
+ # 调用企业接口所需的access_token
236
+ suite_api.get_corp_token(auth_corpid, permanent_code)
237
+
238
+ # 生成授权URL
239
+ suite_api.auth_url(code, uri, state="suite")
240
+
241
+ ```
242
+
243
+ ## 企业号登录授权
244
+
245
+ ```ruby
246
+ # 获取登录授权URL
247
+ # state default 'qy_wechat', option
248
+ # 此处授权回调时会传递auth_code、expires_in,auth_code用于get_login_info(获取企业号管理员登录信息)接口使用
249
+ group_client.auth_login.auth_login_url("redirect_uri", "state")
250
+
251
+ # 获取应用提供商凭证
252
+ # provider_secret:提供商的secret,在提供商管理页面可见
253
+ # 此处会返回:provider_access_token(已通过QyWechatApi.cache缓存7100s)
254
+ group_client.auth_login.get_provider_token(provider_secret)
255
+
256
+ # 通过传递provider_access_token,获取企业号管理员登录信息
257
+ group_client.auth_login.get_login_info(auth_code, provider_access_token)
258
+
259
+ # 通过传递provider_secret,获取企业号管理员登录信息
260
+ group_client.auth_login.get_login_info_by_secret(auth_code, provider_secret)
261
+
262
+ # 获取登录企业号官网的url
263
+ group_client.auth_login.get_login_url(ticket, provider_token, target, agentid=nil)
264
+ ```
265
+
266
+ ## 异步任务接口
267
+
268
+ ```ruby
269
+ # 邀请成员关注
270
+ group_client.async_task.invite_user(callback, invite_info={})
271
+ # 增量更新成员
272
+ group_client.async_task.sync_user(callback, media_id)
273
+ # 全量覆盖成员
274
+ group_client.async_task.replace_user(callback, media_id)
275
+ # 全量覆盖部门
276
+ group_client.async_task.replace_party(callback, media_id)
277
+ # 获取异步任务结果
278
+ group_client.async_task.get_result(job_id)
279
+ ```
280
+
281
+ ## 获取js api签名包
282
+ ```ruby
283
+ group_client.sign_package(request.url)
284
+ ```
285
+
286
+ ## 管理企业号应用
287
+
288
+ ```ruby
289
+ # 获取应用概况列表
290
+ group_client.agent.list
291
+
292
+ # 设置企业号应用
293
+ # agentid 企业应用的id
294
+ # report_location_flag 企业应用是否打开地理位置上报 0:不上报;1:进入会话上报;2:持续上报
295
+ # logo_mediaid 企业应用头像的mediaid,通过多媒体接口上传图片获得mediaid,上传后会自动裁剪成方形和圆形两个头像
296
+ # name 企业应用名称
297
+ # description 企业应用详情
298
+ # redirect_domain 企业应用可信域名
299
+ # isreportuser 是否接收用户变更通知。0:不接收;1:接收
300
+ # isreportenter 是否上报用户进入应用事件。0:不接收;1:接收
301
+ group_client.agent.set()
302
+
303
+ ## 获取企业号应用
304
+ group_client.agent.get(agent_id)
305
+ ```
306
+
307
+ ### 应用套件的回调通知处理
308
+
309
+ Wiki: http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AC%AC%E4%B8%89%E6%96%B9%E5%9B%9E%E8%B0%83%E5%8D%8F%E8%AE%AE
310
+
311
+ ```ruby
312
+ class QyServicesController < ApplicationController
313
+ skip_before_filter :verify_authenticity_token, only: :receive_ticket
314
+
315
+ # TODO: 需要创建表: suites
316
+ def receive_ticket
317
+ param_xml = request.body.read
318
+ aes_key = "NJgquXf6vnYlGpD5APBqlndAq7Nx8fToiEz5Wbaka47"
319
+ aes_key = Base64.decode64("#{aes_key}=")
320
+ hash = MultiXml.parse(param_xml)['xml']
321
+ @body_xml = OpenStruct.new(hash)
322
+ suite_id = "tj86cd0f5b8f7ce20d"
323
+ content = QyWechat::Prpcrypt.decrypt(aes_key, @body_xml.Encrypt, suite_id)[0]
324
+ hash = MultiXml.parse(content)["xml"]
325
+ Rails.logger.info hash
326
+ render text: "success"
327
+ # {"SuiteId"=>"tj86cd0f5b8f7ce20d",
328
+ # "SuiteTicket"=>"Pb5M0PEQFZSNondlK1K_atu2EoobY9piMcQCdE3URiCG3aTwX5WBTQaSsqCzaD-0",
329
+ # "InfoType"=>"suite_ticket",
330
+ # "TimeStamp"=>"1426988061"}
331
+ end
332
+ end
333
+ ```
334
+
335
+ ### 企业号消息接口
336
+
337
+ Wiki: http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E
338
+
339
+ ```ruby
340
+ group_client.chat.send_single_text(sender, user_id, msg)
341
+ group_client.chat.send_single_image(sender, user_id, media_id)
342
+ group_client.chat.send_single_file(sender, user_id, media_id)
343
+ group_client.chat.send_group_text(sender, chat_id, msg)
344
+ group_client.chat.send_group_image(sender, chat_id, media_id)
345
+ group_client.chat.send_group_file(sender, chat_id, media_id)
346
+ ```
347
+
348
+ ### 企业客服服务
349
+
350
+ Wiki: http://qydev.weixin.qq.com/wiki/index.php?title=企业客服接口说明
351
+
352
+ ```ruby
353
+ # msg_struct请根据文档结构拼接传入
354
+ group_client.kf.send(msg_struct)
355
+ ```
356
+
357
+ ### 企业号摇一摇周边
358
+
359
+ Wiki: http://qydev.weixin.qq.com/wiki/index.php?title=获取设备及用户信息
360
+
361
+ ```ruby
362
+ # 获取设备及用户信息
363
+ # 摇周边业务的ticket,可在摇到的URL中得到,ticket生效时间为30分钟,每一次摇都会重新生成新的ticket
364
+ group_client.get_shake_info(ticket)
365
+ ```
366
+
367
+ ## 捐赠支持
368
+
369
+ 如果你觉得我的gem对你有帮助,欢迎打赏支持,:smile:
370
+
371
+ ![](https://raw.githubusercontent.com/lanrion/my_config/master/imagex/donation_me_wx.jpg)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/lib/yol_sso.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'roxml'
2
+ require 'multi_xml'
3
+ require 'ostruct'
4
+ require 'net/http'
5
+ require 'json'
6
+
7
+ require "yol_sso/version"
8
+
9
+ require "yol_sso/models/configuration"
10
+ require "yol_sso/models/encrypt_message"
11
+ require "yol_sso/helpers/prpcrypt"
12
+
13
+ require "yol_sso/connection"
14
+ require "yol_sso/client"
15
+
16
+ module YolSso
17
+
18
+ class << self
19
+
20
+ # A Sso configuration object. See Sso::Configuration.
21
+ attr_writer :configuration
22
+
23
+ def configure
24
+ yield(configuration)
25
+ end
26
+
27
+ def configuration
28
+ @configuration ||= Configuration.new
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ require "monitor"
2
+ require "redis"
3
+ require 'digest/md5'
4
+ module YolSso
5
+ class Client
6
+
7
+ include Connection::Base
8
+ include Connection::Message
9
+
10
+ attr_accessor :host
11
+
12
+ attr_accessor :agentid
13
+
14
+ def initialize(options = {})
15
+ @host = options[:host] || Sso.configuration.host
16
+ @agentid = options[:agentid] || Sso.configuration.agentid
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/connections/*.rb"].each do |path|
2
+ require path
3
+ end
@@ -0,0 +1,60 @@
1
+ module YolSso
2
+ module Connection
3
+ module Base
4
+ def http_post(url, params)
5
+ uri = URI(url)
6
+ req = Net::HTTP.new(uri.host, uri.port)
7
+ header = {'content-type': 'application/json'}
8
+ req.use_ssl = true if uri.scheme == 'https'
9
+ res = req.post("#{uri.path}?#{uri.query}", params.to_json, header)
10
+ handle_res(res)
11
+ end
12
+
13
+ def http_get(url)
14
+ uri = URI(url)
15
+ req = Net::HTTP.new(uri.host, uri.port)
16
+ req.use_ssl = true if uri.scheme == 'https'
17
+ res = req.get("#{uri.path}?#{uri.query}")
18
+ handle_res(res)
19
+ end
20
+
21
+ def get_access_token
22
+ if redis.nil?
23
+ access_token_res = get_token(corpid, secret)
24
+ access_token = access_token_res["access_token"] rescue nil
25
+ else
26
+ access_token = redis.get("qywx_access_token")
27
+ if access_token.nil?
28
+ access_token_res = get_token(corpid, secret)
29
+ access_token = access_token_res["access_token"] rescue nil
30
+ if access_token.nil?
31
+ raise Exception.new("QyWeixin access token authorize false, corpid: #{corpid}")
32
+ else
33
+ redis.set("qywx_access_token", access_token)
34
+ redis.expire("qywx_access_token", 7200)
35
+ end
36
+ end
37
+ end
38
+ access_token
39
+ end
40
+
41
+ private
42
+
43
+ def get_token(app_id, app_secret)
44
+ http_get(token_url(app_id, app_secret))
45
+ end
46
+
47
+ def token_url(corpid, secret)
48
+ "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=#{corpid}&corpsecret=#{secret}"
49
+ end
50
+
51
+ def handle_res(res)
52
+ if res.code == '200'
53
+ return JSON.parse(res.body)
54
+ else
55
+ return {:code => res.code}.to_json
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ module YolSso
2
+ module Connection
3
+ module Message
4
+ def send_message(body)
5
+ http_post(send_url, body.merge("agentid": agentid))
6
+ end
7
+
8
+ private
9
+
10
+ def send_url
11
+ "#{host}messages"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module YolSso
4
+ module PKCS7Encoder
5
+ extend self
6
+
7
+ BLOCK_SIZE = 32
8
+
9
+ def decode(text)
10
+ pad = text[-1].ord
11
+ pad = 0 if (pad < 1 || pad > BLOCK_SIZE)
12
+ size = text.size - pad
13
+ text[0...size]
14
+ end
15
+
16
+ # 对需要加密的明文进行填充补位
17
+ # 返回补齐明文字符串
18
+ def encode(text)
19
+ # 计算需要填充的位数
20
+ amount_to_pad = BLOCK_SIZE - (text.length % BLOCK_SIZE)
21
+ amount_to_pad = BLOCK_SIZE if amount_to_pad == 0
22
+ # 获得补位所用的字符
23
+ pad_chr = amount_to_pad.chr
24
+ "#{text}#{pad_chr * amount_to_pad}"
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ require "yol_sso/helpers/pkcs7_encoder"
3
+ module YolSso
4
+ module Prpcrypt
5
+ extend self
6
+
7
+ # 对密文进行解密.
8
+ # text 需要解密的密文
9
+ def decrypt(aes_key, text, app_id)
10
+ status = 200
11
+ text = Base64.decode64(text)
12
+ text = handle_cipher(:decrypt, aes_key, text)
13
+ result = PKCS7Encoder.decode(text)
14
+ content = result[16...result.length]
15
+ len_list = content[0...4].unpack("N")
16
+ xml_len = len_list[0]
17
+ xml_content = content[4...4 + xml_len]
18
+ from_app_id = content[xml_len + 4...content.size]
19
+ # TODO: refactor
20
+ if app_id != from_app_id
21
+ # raise BizErr, "#{__FILE__}:#{__LINE__} Failure because app_id != from_app_id"
22
+ status = 500
23
+ end
24
+ [xml_content, status]
25
+ end
26
+
27
+ # 加密
28
+ def encrypt(aes_key, text, app_id)
29
+ text = text.force_encoding("ASCII-8BIT")
30
+ random = SecureRandom.hex(8)
31
+ msg_len = [text.length].pack("N")
32
+ text = "#{random}#{msg_len}#{text}#{app_id}"
33
+ text = PKCS7Encoder.encode(text)
34
+ text = handle_cipher(:encrypt, aes_key, text)
35
+ Base64.encode64(text)
36
+ end
37
+
38
+ private
39
+ def handle_cipher(action, aes_key, text)
40
+ cipher = OpenSSL::Cipher.new('AES-256-CBC')
41
+ cipher.send(action)
42
+ cipher.padding = 0
43
+ cipher.key = aes_key
44
+ cipher.iv = aes_key[0...16]
45
+ cipher.update(text) + cipher.final
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ module YolSso
2
+ class Configuration
3
+
4
+ OPTIONS = [:host, :agentid].freeze
5
+
6
+ attr_accessor :host
7
+
8
+ attr_accessor :agentid
9
+
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ # 标准的回包
3
+ # <xml>
4
+ # <Encrypt><![CDATA[msg_encrypt]]></Encrypt>
5
+ # <MsgSignature><![CDATA[msg_signature]]></MsgSignature>
6
+ # <TimeStamp>timestamp</TimeStamp>
7
+ # <Nonce><![CDATA[nonce]]></Nonce>
8
+ # </xml>
9
+
10
+ module YolSso
11
+ class EncryptMessage
12
+ include ROXML
13
+ xml_name :xml
14
+
15
+ xml_accessor :Encrypt, :cdata => true
16
+ xml_accessor :Nonce, :cdata => true
17
+ xml_accessor :TimeStamp, :as => Integer
18
+ xml_accessor :MsgSignature, :cdata => true
19
+
20
+ def to_xml
21
+ super.to_xml(:encoding => 'UTF-8', :indent => 0, :save_with => 0)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module YolSso
2
+ VERSION = "0.0.1"
3
+ end
data/pkg/.DS_Store ADDED
Binary file
data/yol_sso.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'yol_sso/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "yol_sso"
8
+ spec.version = YolSso::VERSION
9
+ spec.authors = ["luojie"]
10
+ spec.email = ["luojie@yolanda.hk"]
11
+ spec.summary = %q{Yolanda middleware for Message.}
12
+ spec.description = ""
13
+ spec.homepage = "https://github.com/luojie2019/yol_sso"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency 'nokogiri'
25
+ spec.add_dependency 'multi_xml'
26
+ spec.add_dependency 'roxml'
27
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yol_sso
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - luojie
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: multi_xml
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: roxml
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: ''
84
+ email:
85
+ - luojie@yolanda.hk
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".DS_Store"
91
+ - Gemfile
92
+ - Gemfile.lock
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/yol_sso.rb
97
+ - lib/yol_sso/client.rb
98
+ - lib/yol_sso/connection.rb
99
+ - lib/yol_sso/connections/base.rb
100
+ - lib/yol_sso/connections/message.rb
101
+ - lib/yol_sso/helpers/pkcs7_encoder.rb
102
+ - lib/yol_sso/helpers/prpcrypt.rb
103
+ - lib/yol_sso/models/configuration.rb
104
+ - lib/yol_sso/models/encrypt_message.rb
105
+ - lib/yol_sso/version.rb
106
+ - pkg/.DS_Store
107
+ - yol_sso.gemspec
108
+ homepage: https://github.com/luojie2019/yol_sso
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.7.9
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Yolanda middleware for Message.
132
+ test_files: []