添加oauth接口
This commit is contained in:
parent
317e940fb0
commit
075fd9670f
|
@ -451,6 +451,8 @@ class AccountController < ApplicationController
|
|||
eval("code = " + "/^" + home_url.gsub(/\//,"\\\/") + "\\\/*(welcome)?\\\/*(\\\/index\\\/*.*)?\$/")
|
||||
if (code=~params[:back_url] || params[:back_url].to_s.include?('lost_password')) && last_login_on != ''
|
||||
redirect_to user_activities_path(user,host: Setting.host_user)
|
||||
elsif params[:back_url]
|
||||
redirect_to params[:back_url]
|
||||
else
|
||||
if last_login_on == ''
|
||||
redirect_to my_account_url
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
class OauthController < ApplicationController
|
||||
before_filter :user_setup
|
||||
before_filter :require_login, only: [:authorize]
|
||||
|
||||
# 客户端申请认证的URI,包含以下参数:
|
||||
#
|
||||
# response_type:表示授权类型,必选项,此处的值固定为”code”
|
||||
# client_id:表示客户端的ID,必选项
|
||||
# redirect_uri:表示重定向URI,可选项
|
||||
# scope:表示申请的权限范围,可选项
|
||||
# state:表示客户端的当前状态,可以指定任意值(最好是随机字符串),认证服务器会原封不动地返回这个值,可防止CSRF攻击
|
||||
#
|
||||
# 这个页显示授权页,如果授权成功,返回redirect_uri+code
|
||||
#
|
||||
#
|
||||
# 服务器回应客户端的URI,包含以下参数:
|
||||
#
|
||||
# code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次, 否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
|
||||
# state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。
|
||||
def authorize
|
||||
|
||||
#参数检查
|
||||
raise "response_type只能为code" unless params["response_type"] != "code"
|
||||
raise "client_id为必传项" unless params["client_id"].present?
|
||||
raise "redirect_uri为必传项" unless params["redirect_uri"].present?
|
||||
|
||||
|
||||
config = OauthConfig.where(client_id: params["client_id"], redirect_uri: params["redirect_uri"]).first
|
||||
raise "client_id或redirect_uri不正确" unless config
|
||||
|
||||
|
||||
@data = params
|
||||
|
||||
if params[:gen_code]
|
||||
## 检查通过,生成code
|
||||
oauth = Oauth.create!(client_id: config.client_id,
|
||||
client_secret: config.client_secret,
|
||||
redirect_uri: config.redirect_uri
|
||||
)
|
||||
code = oauth.gen_code
|
||||
|
||||
redirect_to params["redirect_uri"] + "?code=#{code}&state=#{params[:state]}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_callback
|
||||
# 申请 token
|
||||
#
|
||||
client_id = "88d893c5a345313e7b8c6fcf23d3d024ee08d5e41ce120c3448b6eea77d8de30"
|
||||
client_secret = "e9240cc5fc913741db5aea93f2986a8ea0631bb67f7c00e41e491b95d9619e64"
|
||||
redirect_uri = "http://localhost:3000/oauth/cb"
|
||||
url = "http://127.0.0.1:3000/oauth/token?grant_type=authorization_code&code=#{params['code']}"
|
||||
+"&redirect_uri=#{redirect_uri}&client_id=#{client_id}&client_secret=#{client_secret}"
|
||||
|
||||
render text: url
|
||||
end
|
||||
|
||||
|
||||
# 客户端向认证服务器申请令牌的HTTP请求,包含以下参数:
|
||||
#
|
||||
# grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。
|
||||
# code:表示上一步获得的授权码,必选项。
|
||||
# redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
|
||||
# client_id:表示客户端ID,必选项。
|
||||
# client_secret: 表示客户端密钥,必选项。
|
||||
#
|
||||
#
|
||||
# 认证服务器核对了授权码和”重定向URI”,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
|
||||
#
|
||||
# 认证服务器发送的HTTP回复,包含以下内容:
|
||||
#
|
||||
# access_token:表示访问令牌,必选项。
|
||||
# token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
|
||||
# expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
|
||||
# refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
|
||||
# scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
|
||||
def token
|
||||
|
||||
if params[:grant_type] == 'authorization_code'
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def require_login
|
||||
if !User.current.logged?
|
||||
redirect_to '/login?back_url='+request.original_url
|
||||
end
|
||||
end
|
||||
|
||||
include Trustie::Http
|
||||
|
||||
end
|
|
@ -48,38 +48,6 @@ class OschinaController < ApplicationController
|
|||
|
||||
|
||||
private
|
||||
def get(url)
|
||||
uri = URI(url)
|
||||
res = Net::HTTP.start(uri.host, uri.port, use_ssl: url.start_with?('https')) do |http|
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
#req['Content-Type'] = 'application/json'
|
||||
# The body needs to be a JSON string, use whatever you know to parse Hash to JSON
|
||||
#req.body = {a: 1}.to_json
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
res.body
|
||||
end
|
||||
|
||||
def post(url)
|
||||
uri = URI(url)
|
||||
res = Net::HTTP.start(uri.host, uri.port, use_ssl: url.start_with?('https')) do |http|
|
||||
req = Net::HTTP::Post.new(uri)
|
||||
#req['Content-Type'] = 'application/json'
|
||||
# The body needs to be a JSON string, use whatever you know to parse Hash to JSON
|
||||
#req.body = {a: 1}.to_json
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
res.body
|
||||
end
|
||||
|
||||
def decode(s)
|
||||
begin
|
||||
obj = ActiveSupport::JSON.decode(s)
|
||||
rescue ActiveSupport::JSON.parse_error
|
||||
logger.error("Attempted to decode invalid JSON: #{s}")
|
||||
end
|
||||
end
|
||||
include Trustie::Http
|
||||
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
require 'base64'
|
||||
|
||||
class Oauth < ActiveRecord::Base
|
||||
attr_accessible :client_id, :client_secret, :redirect_uri
|
||||
|
||||
|
||||
def gen_code
|
||||
code = Base64.urlsafe_encode64 Digest::MD5.hexdigest "#{Time.now}-#{Random.new_seed}"
|
||||
update_column(:code, code)
|
||||
code
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class OauthConfig < ActiveRecord::Base
|
||||
attr_accessible :client_id, :client_secret, :redirect_uri, :scope
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
授权页
|
||||
|
||||
|
||||
<p>当前用户: <%= current_user.login %></p>
|
||||
|
||||
<p>
|
||||
|
||||
|
||||
<%= form_for oauth_authorize_path do%>
|
||||
<input type="hidden" name="gen_code" value="true">
|
||||
<input type="hidden" name="client_id" value="<%= @data["client_id"] %>">
|
||||
<input type="hidden" name="redirect_uri" value="<%= @data["redirect_uri"] %>">
|
||||
<input type="hidden" name="response_type" value="<%= @data["response_type"] %>">
|
||||
<input type="hidden" name="scope" value="<%= @data["scope"] %>">
|
||||
<input type="hidden" name="state" value="<%= @data["state"] %>">
|
||||
<button type="submit">是否授权</button>
|
||||
<% end %>
|
||||
|
||||
</p>
|
|
@ -558,6 +558,11 @@ RedmineApp::Application.routes.draw do
|
|||
match 'oschina/login', to: 'oschina#login', :via => :get
|
||||
match 'oschina/login_cb', to: 'oschina#login_callback', :via => [:get, :post]
|
||||
|
||||
## oauth相关
|
||||
match 'oauth/authorize', to: 'oauth#authorize', :via => [:get, :post]
|
||||
match 'oauth/token', to: 'oauth#token', :via => :post
|
||||
match 'oauth/cb', to: 'oauth#test_callback', :via => :get
|
||||
|
||||
# boards
|
||||
match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message'
|
||||
match 'boards/:id/join_to_org_subfields', :to => 'boards#join_to_org_subfields'
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
class CreateOauth < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :oauth do |t|
|
||||
t.string :client_id
|
||||
t.string :client_secret
|
||||
t.string :code
|
||||
t.string :redirect_uri
|
||||
t.string :scope
|
||||
|
||||
t.string :access_token
|
||||
t.string :refresh_token
|
||||
t.integer :token_created_at
|
||||
t.integer :token_expires_in #过期时间
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
class CreateOauthConfigs < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :oauth_configs do |t|
|
||||
t.string :client_id
|
||||
t.string :client_secret
|
||||
t.string :redirect_uri
|
||||
t.string :scope
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
|
||||
OauthConfig.create(
|
||||
client_id: '88d893c5a345313e7b8c6fcf23d3d024ee08d5e41ce120c3448b6eea77d8de30',
|
||||
client_secret: 'e9240cc5fc913741db5aea93f2986a8ea0631bb67f7c00e41e491b95d9619e64',
|
||||
redirect_uri: 'http://localhost:3000/oschina/login_cb',
|
||||
scope: ''
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
end
|
25
db/schema.rb
25
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20181121032918) do
|
||||
ActiveRecord::Schema.define(:version => 20181121071704) do
|
||||
|
||||
create_table "activities", :force => true do |t|
|
||||
t.integer "act_id", :null => false
|
||||
|
@ -1501,6 +1501,29 @@ ActiveRecord::Schema.define(:version => 20181121032918) do
|
|||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "oauth_configs", :force => true do |t|
|
||||
t.string "client_id"
|
||||
t.string "client_secret"
|
||||
t.string "redirect_uri"
|
||||
t.string "scope"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "oauths", :force => true do |t|
|
||||
t.string "client_id"
|
||||
t.string "client_secret"
|
||||
t.string "code"
|
||||
t.string "redirect_uri"
|
||||
t.string "scope"
|
||||
t.string "access_token"
|
||||
t.string "refresh_token"
|
||||
t.integer "token_created_at"
|
||||
t.integer "token_expires_in"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "onclick_times", :force => true do |t|
|
||||
t.integer "user_id"
|
||||
t.datetime "onclick_time"
|
||||
|
|
|
@ -4,3 +4,4 @@ require 'trustie/gitlab/api'
|
|||
require 'trustie/grack/grack'
|
||||
require 'trustie/at/at'
|
||||
require 'trustie/sms/sms'
|
||||
require 'trustie/http/http'
|
|
@ -0,0 +1,46 @@
|
|||
#coding=utf-8
|
||||
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
|
||||
|
||||
module Trustie
|
||||
module Http
|
||||
|
||||
def get(url)
|
||||
uri = URI(url)
|
||||
res = Net::HTTP.start(uri.host, uri.port, use_ssl: url.start_with?('https')) do |http|
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
#req['Content-Type'] = 'application/json'
|
||||
# The body needs to be a JSON string, use whatever you know to parse Hash to JSON
|
||||
#req.body = {a: 1}.to_json
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
res.body
|
||||
end
|
||||
|
||||
def post(url, data=nil)
|
||||
uri = URI(url)
|
||||
res = Net::HTTP.start(uri.host, uri.port, use_ssl: url.start_with?('https')) do |http|
|
||||
req = Net::HTTP::Post.new(uri)
|
||||
#req['Content-Type'] = 'application/json'
|
||||
# The body needs to be a JSON string, use whatever you know to parse Hash to JSON
|
||||
req.body = data if data
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
res.body
|
||||
end
|
||||
|
||||
def decode(s)
|
||||
begin
|
||||
obj = ActiveSupport::JSON.decode(s)
|
||||
rescue ActiveSupport::JSON.parse_error
|
||||
logger.error("Attempted to decode invalid JSON: #{s}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue