我有一个Rails 5.2应用程序,它使用Devise 4.4.1和devise_ldap_authenticatable
进行身份验证。我尝试将其切换为devise_cas_authenticatable
,现在在CAS登录页面输入我的凭据后进入重定向循环。
应用程序,CAS服务器(rubycas-server
),LDAP和数据库都通过Docker Compose作为Docker容器运行。 CAS服务器配置为使用HTTP进行开发。
据我所知,我的应用程序在登录后CAS返回时没有设置会话,但我不明白为什么。非常感谢收到一些调试指针。
以下是每次重定向重复的日志部分:
app_1 | Started GET "/" for 172.18.0.1 at 2018-03-05 11:10:33 +0000
app_1 | (0.3ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
app_1 | ↳ /usr/local/bundle/gems/activerecord-5.2.0.rc1/lib/active_record/log_subscriber.rb:98
app_1 | (0.3ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
app_1 | ↳ /usr/local/bundle/gems/activerecord-5.2.0.rc1/lib/active_record/log_subscriber.rb:98
app_1 | Processing by HomeController#index as HTML
app_1 | ### Params: <ActionController::Parameters {"controller"=>"home", "action"=>"index"} permitted: false>
app_1 | ### Referrer:
app_1 | ### Session: nil
app_1 | Completed 401 Unauthorized in 11ms (ActiveRecord: 0.0ms)
app_1 |
app_1 |
app_1 | Started GET "/users/sign_in" for 172.18.0.1 at 2018-03-05 11:10:34 +0000
app_1 | Processing by Devise::CasSessionsController#new as HTML
app_1 | ### Params: <ActionController::Parameters {"controller"=>"devise/cas_sessions", "action"=>"new"} permitted: false>
app_1 | ### Referrer:
app_1 | ### Session: nil
app_1 | Redirected to http://cas:8080/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice
app_1 | Completed 302 Found in 6ms (ActiveRecord: 0.0ms)
app_1 |
app_1 |
cas_1 | 172.18.0.1 - - [05/Mar/2018:11:10:34 UTC] "GET /cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice HTTP/1.1" 200 2517
cas_1 | - -> /cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice
cas_1 | 172.18.0.1 - - [05/Mar/2018:11:10:38 UTC] "POST /cas/login HTTP/1.1" 303 0
cas_1 | http://cas:8080/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice -> /cas/login
app_1 | Started GET "/users/service?ticket=ST-1520248238rDxT--HBG7GmKRhNydV" for 172.18.0.1 at 2018-03-05 11:10:38 +0000
app_1 | Processing by Devise::CasSessionsController#service as HTML
app_1 | Parameters: {"ticket"=>"ST-1520248238rDxT--HBG7GmKRhNydV"}
app_1 | ### Params: <ActionController::Parameters {"ticket"=>"ST-1520248238rDxT--HBG7GmKRhNydV", "controller"=>"devise/cas_sessions", "action"=>"service"} permitted: false>
app_1 | ### Referrer: http://cas:8080/cas/login?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice
cas_1 | railsapp_app_1.railsapp_rails-app-test-net - - [05/Mar/2018:11:10:38 UTC] "GET /cas/proxyValidate?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice&ticket=ST-1520248238rDxT--HBG7GmKRhNydV HTTP/1.1" 200 263
cas_1 | - -> /cas/proxyValidate?service=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fservice&ticket=ST-1520248238rDxT--HBG7GmKRhNydV
app_1 | Using conditions {username => student_sd} to find the User
app_1 | User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`username` = 'student_sd' ORDER BY `users`.`id` ASC LIMIT 1
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | (0.4ms) BEGIN
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | User Exists (0.5ms) SELECT 1 AS one FROM `users` WHERE `users`.`username` = 'student_sd' LIMIT 1
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` IS NULL LIMIT 1
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | (0.4ms) ROLLBACK
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | (0.3ms) BEGIN
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`username` = 'student_sd' LIMIT 1
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` IS NULL LIMIT 1
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | (0.3ms) ROLLBACK
app_1 | ↳ app/controllers/application_controller.rb:44
app_1 | ### Session: {}
app_1 | Redirected to http://localhost:3000/
app_1 | Completed 302 Found in 90ms (ActiveRecord: 6.7ms)
这是我的ApplicationController:
class ApplicationController < ActionController::Base
rescue_from ActionController::RoutingError do
redirect_to root_path, alert: 'Page not found'
end
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :do_authenticate!
def scoped_user
return nil if scoped_username.blank?
@_scoped_user ||= User.includes(:courses).find_by(username: scoped_username)
end
helper_method :scoped_user
def select_for_admin(option_of_the_proletariat, admin_option)
if admin_mode?
admin_option
else
option_of_the_proletariat
end
end
helper_method :select_for_admin
def admin_mode?
user_signed_in? && (scoped_user != current_user)
end
helper_method :admin_mode?
protected
def do_authenticate!
puts "### Params: #{params.inspect}" # debug
puts "### Referrer: #{request.referer}"
puts "### Session: #{user_session.inspect}"
authenticate_user!
end
def allow_admin_only
puts "allow_admin_only" # debug
block_unauthorised! unless current_user.administrator?
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_in, keys: [:username])
end
def block_unauthorised!
puts "block_unauthorised!" # debug
raise ActionController::RoutingError.new('Not found')
end
def scoped_username
params[:username]
end
end
如果它有用,我的用户模型:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :cas_authenticatable, :trackable, :rememberable
has_many :memberships
has_many :courses, through: :memberships
has_many :images, through: :memberships
before_create :fetch_user_attributes
validates :username, presence: true, uniqueness: { case_sensitive: false }
validates :name, presence: true
validates :email, presence: true, uniqueness: { case_sensitive: false }
validates :department, presence: true
validates :employee_type, presence: true
scope :search, ->(query) {
where('username LIKE ?', "%#{query}%").or(where('name LIKE ?', "%#{query}%"))
}
def member_of?(course)
courses.include?(course)
end
def owned_tag_names
::Gutentag::Tag
.joins(:taggings)
.joins('join images on images.id = gutentag_taggings.taggable_id')
.joins('join memberships on images.membership_id = memberships.id')
.where('memberships.user_id = ?', self.id)
.distinct
.pluck(:name)
end
# "hack for remember_token" from devise_ldap_authenticatable wiki
def authenticatable_salt
Digest::SHA1.hexdigest(username)[0, 29]
end
def to_param
username
end
def fetch_user_attributes
# hard code values for testing
raise '### Tried to fetch attributes'
assign_attributes({
email: "user-#{('a'..'z').to_a.shuffle[0,8].join}@example.ac.uk",
name: 'User Person',
department: 'DEN',
employee_type: 'student'
})
# {
# email: Devise::LDAP::Adapter.get_ldap_param(username, 'mail').first,
# name: Devise::LDAP::Adapter.get_ldap_param(username, 'cn').first,
# department: Devise::LDAP::Adapter.get_ldap_param(username, 'ou').first,
# employee_type: Devise::LDAP::Adapter.get_ldap_param(username, 'employeeType').first
# }
end
end
答案 0 :(得分:0)
devise_ldap_authenticatable
调用resource.save
时出现问题。验证在 before_create
回调之前运行,并且这些验证错误无声地阻止用户被创建并因此进行身份验证。电子邮件字段中的唯一性验证是日志通过电子邮件显示SELECT
的原因。
解决方案是改变
before_create :fetch_user_attributes
到
before_validation :fetch_user_attributes, on: :create
请参阅this issue。