2
下面的simple_client.rb文件對我的模擬cas服務器完全正常工作;但是,casport.rb文件(oa-casport OmniAuth策略的主文件)沒有正確設置或傳遞標題/格式。它需要動態分配給類,以允許初始化選項能夠創建它們,但我不知道除了我在這裏嘗試做什麼以外還有什麼別的辦法。我相當確定我在某個時候有這個工作,但是我看不到任何其他解釋,爲什麼在客戶端文件簡單的情況下這不起作用。如何動態地在我的類上設置HTTParty配置參數?
任何幫助都非常感謝在搞清楚如何在我的Casport類中動態地最佳地設置HTTParty的format
和headers
設置。因爲它只是不斷返回該特定用戶的HTML視圖。
simple_client.rb:
### simple_client.rb - works properly w/ parsed XML response
### The cas.dev project is coming from this Github repo:
### https://github.com/stevenhaddox/oa-casport-server
require 'rubygems'
require 'httparty'
require 'awesome_print'
class Casport
include HTTParty
base_uri 'cas.dev/users'
format :xml
headers 'Accept' => 'application/xml'
def self.find_user(id)
get("/#{id}").parsed_response
end
end
user = Casport.find_user(1)
ap user
casport.rb:
# lib/omniauth/strategies/casport.rb
require 'omniauth/core'
require 'httparty'
require 'redis'
require 'uri'
module OmniAuth
module Strategies
#
# Authentication to CASPORT
#
# @example Basic Usage
#
# use OmniAuth::Strategies::Casport, {
# :setup => true
# }
# @example Full Options Usage
#
# use OmniAuth::Strategies::Casport, {
# :setup => true,
# :cas_server => 'http://cas.slkdemos.com/users/',
# :format => 'xml',
# :format_header => 'application/xml',
# :ssl_ca_file => 'path/to/ca_file.crt',
# :pem_cert => '/path/to/cert.pem',
# :pem_cert_pass => 'keep it secret, keep it safe.'
# }
class Casport
include OmniAuth::Strategy
include HTTParty
def initialize(app, options)
super(app, :casport)
@options = options
@options[:cas_server] ||= 'http://cas.dev/users'
@options[:format] ||= 'xml'
@options[:format_header] ||= 'application/xml'
end
def request_phase
Casport.setup_httparty(@options)
redirect(callback_path)
end
def callback_phase
begin
raise 'We seemed to have misplaced your credentials... O_o' if user.nil?
super
rescue => e
redirect(request_path)
# fail!(:invalid_credentials, e)
end
call_app!
end
def auth_hash
# store user in a local var to avoid new method calls for each attribute
# convert all Java camelCase keys to Ruby snake_case, it just feels right!
user_obj = user.inject({}){|memo, (k,v)| memo[k.gsub(/[A-Z]/){|c| '_'+c.downcase}] = v; memo}
begin
user_obj = user_obj['userinfo']
rescue => e
fail!(:invalid_user, e)
end
OmniAuth::Utils.deep_merge(super, {
'uid' => user_obj['uid'],
'user_info' => {
'name' => user_obj['full_name'],
'email' => user_obj['email']
},
'extra' => {'user_hash' => user_obj}
})
end
# Set HTTParty params that we need to set after initialize is called
# These params come from @options within initialize and include the following:
# :ssl_ca_file - SSL CA File for SSL connections
# :format - 'json', 'xml', 'html', etc. || Defaults to 'xml'
# :format_header - :format Header string || Defaults to 'application/xml'
# :pem_cert - /path/to/a/pem_formatted_certificate.pem for SSL connections
# :pem_cert_pass - plaintext password, not recommended!
def self.setup_httparty(opts)
format opts[:format].to_sym
headers 'Accept' => opts[:format_header]
if opts[:ssl_ca_file]
ssl_ca_file opts[:ssl_ca_file]
if opts[:pem_cert_pass]
pem File.read(opts[:pem_cert]), opts[:pem_cert_pass]
else
pem File.read(opts[:pem_cert])
end
end
end
def user
# Can't get user data without a UID from the application
begin
raise "No UID set in request.env['omniauth.strategy'].options[:uid]" if @options[:uid].nil?
@options[:uid] = @options[:uid].to_s
rescue => e
fail!(:uid_not_found, e)
end
url = URI.escape(@options[:cas_server] + '/' + @options[:uid])
# It appears the headers aren't going through properly to HTTParty...
# The URL + .xml works in the application & the url w/out .xml works in standalone file
# Which means somehow the setup with self.setup_httparty isn't kicking in properly :(
ap Casport.get(url+'.xml').parsed_response
begin
cache = @options[:redis_options].nil? ? Redis.new : Redis.new(@options[:redis_options])
unless @user = (cache.get @options[:uid])
# User is not in the cache
# Retrieving the user data from CASPORT
# {'userinfo' => {{'uid' => UID}, {'fullName' => NAME},...}},
@user = Casport.get(url).parsed_response
cache.set @options[:uid], @user
# CASPORT expiration time for user (24 hours => 1440 seconds)
cache.expire @options[:uid], 1440
end
# If we can't connect to Redis...
rescue Errno::ECONNREFUSED => e
@user ||= Casport.get(url).parsed_response
end
@user = nil if user_empty?
@user
end
# Investigate user_obj to see if it's empty (or anti-pattern data)
def user_empty?
is_empty = false
is_empty = true if @user.nil?
is_empty = true if @user.empty?
# If it isn't empty yet, let's convert it into a Hash object for easy parsing via eval
unless @user.class == Hash
is_empty = true
raise "String returned when a Hash was expected."
end
is_empty == true ? true : nil
end
end
end
end
對我來說,這個答案的最好的部分是它展示瞭如何使用'headers'原語添加_multiple_標頭。 –