我正在运行带有轨道3.0.7的装置1.3.4。用户可以通过两种方式登录:使用web应用程序和使用移动web应用程序(通过JSON API调用)。第一种方式由默认的设计会话控制器完美地处理。身份验证的API-call方法需要位于扩展我的Api::BaseController
的控制器中。所以,我写了这样的第二个控制器:
class Api::UserSessionsController < Api::BaseController
…
def create
user = warden.authenticate(:scope => :user)
if user
sign_in(:user, user)
else
# Do some error handling
end
end
end
由于Devise::Strategies::Authenticatable
中的valid_controller?
方法,尝试通过此方法登录失败。因为我将默认控制器(devise/sessions
)保留为用户的映射控制器,所以它不允许来自我的自定义控制器的身份验证。
我想将我的自定义功能滚动到我自己的Devise::SessionsController
子类中,但我需要API会话控制器来扩展API::BaseController
,因此我也无法扩展Devise::SessionsController
。我不想将工作的、默认的、行为的web-app身份验证方法放在API控制器中,特别是因为这需要从设备控制器复制它们。
有什么建议吗?是否缺少允许多个控制器处理会话的配置?valid_controller?
方法做的是==
比较,而不是.include?
,所以我不知道这是怎么回事。
更新
这是一个糟糕的临时解决方案。我不喜欢它,所以我不会把它作为一个答案发布,但我认为它可能会为你们所有的答案类型提供思考的食物:
在我的create方法的顶部,我可以覆盖Devise期望的会话控制器。
Devise.mappings[:user].controllers[:sessions] = params[:controller]
这是围绕Devise的预期功能(需要一个特定的控制器来创建会话)进行的,所以我不想保留它。我想知道这个限制是一种安全措施还是只是一种约定——如果是为了安全,这可能很糟糕。
我只能建议另一种解决方法(也许不那么糟糕?)在初始化器中,您可以覆盖#valid_controller?,像这样:
require 'devise/strategies/authenticatable'
require 'devise/strategies/database_authenticatable'
class Devise::Strategies::DatabaseAuthenticatable
def valid_controller?
# your logic here
true
end
end
我也很想知道这个限制的原因
我使用Devise 2.2.7和Rails 3.2.13。以上两种方法对我都不起作用:Devise::Strategies::DatabaseAuthenticatable
中的valid_vontroller?
方法已经不存在了。Devise.mappings[:user].controllers[:sessions]
的把戏对我也不起作用。
在浏览了这个线程之后,我发现了valid_params_request?其负责确保该请求应当通过认证系统发送。有一个助手方法,allows_params_authentication!,这使Devise::SessionsController能够处理身份验证请求。
您可以通过以下方式从任何控制器对用户进行身份验证:
def signin
allow_params_authentication!
authenticate_user!
end
如果您想在身份验证失败时重定向到自定义页面:
resource = warden.authenticate!({
:scope => :user,
:recall => "#{controller_path}#login"
})
sign_in(:user, resource)
通过开发一个与Spree Commerce协同工作的引擎,我发现需要在Devise::SessionsController
的子类之外处理身份验证,该引擎已经实现了设计身份验证。