forked from Gitlink/forgeplus
江南 CAS 功能 #485
|
|
@ -0,0 +1,25 @@
|
|||
class Oauth::JiangnanCasController < Oauth::BaseController
|
||||
def create
|
||||
user, is_new_user = Oauth::CreateORFindJiangnanCasUserService.call(check_params)
|
||||
successful_authentication(user)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def verify
|
||||
render json: {
|
||||
"code": 200,
|
||||
"msg": "token验证成功",
|
||||
"data": [{
|
||||
"code": "02020020250912000001",
|
||||
"userName":"XXX",
|
||||
"nickName":"sss",
|
||||
"thirdPartySign": "02020020250912000001",
|
||||
"originPlatform": "00",
|
||||
"expireTime": "xxx"}]
|
||||
}
|
||||
end
|
||||
|
||||
def check_params
|
||||
params.permit(:token, :clientIp)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: open_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# type :string(255)
|
||||
# uid :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# extra :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_open_users_on_type_and_uid (type,uid) UNIQUE
|
||||
# index_open_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OpenUsers::JiangnanCas < OpenUser
|
||||
def nickname
|
||||
extra&.[]('userName')
|
||||
end
|
||||
|
||||
def en_type
|
||||
'jiangnan_cas'
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
class Oauth::CreateORFindJiangnanCasUserService < ApplicationService
|
||||
CONFIG = Rails.application.config_for(:configuration)['jiangnan_cas']
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
result = verify_token(@params[:token], @params[:clientI])
|
||||
|
||||
return [nil, false] unless result[:success]
|
||||
sso_user = result[:user]
|
||||
|
||||
open_user = OpenUsers::JiangnanCas.find_by(uid: sso_user[:code])
|
||||
if open_user.present?
|
||||
open_user.update(extra: sso_user.to_json)
|
||||
|
||||
return [open_user.user, false]
|
||||
end
|
||||
|
||||
user = build_user(sso_user)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
user.save!
|
||||
user.create_user_extension!
|
||||
|
||||
OpenUsers::JiangnanCas.create!(
|
||||
uid: sso_user[:code],
|
||||
user: user,
|
||||
extra: sso_user.to_json
|
||||
)
|
||||
end
|
||||
|
||||
[user, true]
|
||||
end
|
||||
|
||||
private
|
||||
def verify_token(token, client_ip)
|
||||
raise 'jiangnan_cas 未配置' if CONFIG.blank?
|
||||
uri = URI.parse(CONFIG["domain"] + CONFIG["verify_url"])
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
#http.use_ssl = true
|
||||
|
||||
# 如果是自签名证书,可临时关闭验证(正式环境不建议)
|
||||
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
|
||||
request = Net::HTTP::Post.new(uri.request_uri)
|
||||
|
||||
# 请求头
|
||||
request['Content-Type'] = 'application/json'
|
||||
request['en-token-sso-user'] = token
|
||||
|
||||
# 请求体
|
||||
request.body = {
|
||||
clientIp: client_ip
|
||||
}.to_json
|
||||
|
||||
response = http.request(request)
|
||||
|
||||
parse_response(response)
|
||||
rescue URI::InvalidURIError => e
|
||||
error_result("SSO 地址格式错误", e)
|
||||
rescue Net::OpenTimeout => e
|
||||
error_result("SSO 连接超时", e)
|
||||
rescue Net::ReadTimeout => e
|
||||
error_result("SSO 响应超时", e)
|
||||
rescue SocketError => e
|
||||
error_result("SSO 域名或IP无法访问", e)
|
||||
rescue OpenSSL::SSL::SSLError => e
|
||||
error_result("SSO SSL证书异常", e)
|
||||
rescue JSON::ParserError => e
|
||||
error_result("SSO 返回数据不是合法JSON", e)
|
||||
rescue StandardError => e
|
||||
error_result("SSO 验证失败", e)
|
||||
end
|
||||
|
||||
|
||||
|
||||
def parse_response(response)
|
||||
json = JSON.parse(response.body)
|
||||
success = json['code'].to_i == 200
|
||||
user = json['data']&.first || {}
|
||||
|
||||
{
|
||||
success: success,
|
||||
code: json['code'],
|
||||
msg: json['msg'],
|
||||
|
||||
# 原始返回
|
||||
data: json['data'] || [],
|
||||
|
||||
# 直接可用的用户信息
|
||||
user: {
|
||||
code: user['code'],
|
||||
user_name: user['userName'],
|
||||
nick_name: user['nickName'],
|
||||
third_party_sign: user['thirdPartySign'],
|
||||
origin_platform: user['originPlatform'],
|
||||
expire_time: user['expireTime']
|
||||
},
|
||||
|
||||
# http状态码
|
||||
http_status: response.code.to_i
|
||||
}
|
||||
end
|
||||
|
||||
def error_result(message, exception)
|
||||
Rails.logger.error <<~LOG
|
||||
[SSO VERIFY ERROR]
|
||||
message: #{message}
|
||||
error: #{exception.class}
|
||||
detail: #{exception.message}
|
||||
LOG
|
||||
|
||||
{
|
||||
success: false,
|
||||
code: 500,
|
||||
msg: "#{message}:#{exception.message}",
|
||||
data: [],
|
||||
user: nil
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def build_user(sso_user)
|
||||
nickname =
|
||||
sso_user[:nick_name].presence ||
|
||||
sso_user[:user_name].presence ||
|
||||
@params[:comsys_name]
|
||||
|
||||
User.new(
|
||||
login: User.generate_login('J'),
|
||||
type: 'User',
|
||||
status: User::STATUS_ACTIVE,
|
||||
nickname: nickname,
|
||||
lastname: nickname
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -25,6 +25,8 @@ Rails.application.routes.draw do
|
|||
# get 'auth/qq/callback', to: 'oauth/qq#create'
|
||||
get 'auth/failure', to: 'oauth/base#auth_failure'
|
||||
get 'auth/cas/callback', to: 'oauth/cas#create'
|
||||
get 'auth/jiangnan/callback', to: 'oauth/jiangnan_cas#create'
|
||||
post 'auth/jiangnan/verify', to: 'oauth/jiangnan_cas#verify'
|
||||
get 'auth/acge/callback', to: "oauth/acge#create"
|
||||
get 'oauth_ci4s', to: "oauth/ci4s#oauth_url"
|
||||
get 'auth/ci4s/callback', to: "oauth/ci4s#create"
|
||||
|
|
|
|||
Loading…
Reference in New Issue