设计:让多个控制器处理用户会话
我正在使用 Rails 3.0.7 运行 devise 1.3.4。用户可以通过两种方式登录:使用 Web 应用程序和使用移动 Web 应用程序(通过 JSON API 调用)。第一种方式由默认设备会话控制器完美处理。身份验证的 API 调用方法需要位于扩展我的 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< /code>,所以我也无法扩展
Devise::SessionsController
。我不想将工作的、默认行为的 Web 应用程序身份验证方法放置在 API 控制器中,特别是因为这需要从设备控制器复制它们。
有什么建议吗?我是否缺少一些允许多个控制器处理会话的配置? valid_controller?
方法进行 ==
比较,而不是 .include?
,所以我不知道它是如何工作的。
更新
这是一个糟糕的临时解决方法。我不喜欢它,所以我不会将其作为答案发布,但我认为它可能会为所有回答者类型提供思考:
在我的创建方法的顶部,我可以覆盖 Devise 期望的内容成为会话控制器。
Devise.mappings[:user].controllers[:sessions] = params[:controller]
这是围绕 Devise 的预期功能(需要单个特定控制器来创建会话)进行的,因此我不想保留它。我想知道这个限制是一种安全措施还是只是一种约定——如果是为了安全,这可能是相当糟糕的。
I am running devise 1.3.4 with rails 3.0.7. I have two ways users may sign in: using the web app, and using a mobile web app (via a JSON API call). The first way is handled perfectly by the default devise sessions controller. The API-call method of authentication needs to be in a controller that extends my Api::BaseController
. So, I wrote this second controller like this:
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
Attempts to login via this method fail due to the valid_controller?
method in Devise::Strategies::Authenticatable
. Because I have left the default controller (devise/sessions
) as the mapped controller for users, it does not allow authentications from my custom controller.
I would like to roll my custom functionality into my own subclass of Devise::SessionsController
, but I need the API sessions controller to extend the API::BaseController
, so I can't extend Devise::SessionsController
as well. I don't want to place the working, default-behavior web-app authentication methods in the API controller, especially because this would require copying them from the devise controller.
Any suggestions? Is there some config I'm missing that allows multiple controllers to handle sessions? the valid_controller?
method does an ==
comparison, not .include?
, so I don't see how that would work.
UPDATE
This is an awful temporary workaround. I don't like it, so I'm not posting it as an answer, but I thought it might offer food-for-thought to all you answerer-types:
In the top of my create method, I could override what Devise expects to be the sessions controller.
Devise.mappings[:user].controllers[:sessions] = params[:controller]
This is working around Devise's intended functionality (requiring a single, specific controller to do session creation) so I don't want to keep it. I wonder if this constraint is a security measure or just a convention -- if it is for security, this is presumably quite bad.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我只能建议另一种解决方法(也许不那么糟糕?)
在初始化程序中,您可以覆盖#valid_controller?,如下所示:
我也有兴趣了解此约束的原因
I can only suggest another workaround (maybe less awful?)
In an initializer you can overwrite #valid_controller?, like this:
I'd be interested in knowing the reason of this constraint too
我正在使用 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 的原因 处理身份验证请求。
您可以通过以下方式从任何控制器对用户进行身份验证:
如果您想在身份验证失败时重定向到自定义页面:
我发现需要通过开发引擎在
Devise::SessionsController
的子类之外处理身份验证它与 Spree Commerce 一起工作,后者已经实现了设备身份验证。I'm using Devise 2.2.7 with Rails 3.2.13. Both of the above methods did not work for me: the
valid_vontroller?
method inDevise::Strategies::DatabaseAuthenticatable
does not exist anymore. TheDevise.mappings[:user].controllers[:sessions]
trick did not work for me either.After digging through this thread I found valid_params_request? which is responsible for ensuring that the request should be sent through the authentication system. There is a helper method, allows_params_authentication!, which is what enables the Devise::SessionsController to process authentication requests.
You can authenticate a user from any controller by:
If you want to redirect to a custom page when authentication fails:
I came across the need for handling authentication outside a subclass of
Devise::SessionsController
by developing an engine that works alongside of Spree Commerce, which already implements devise authentication.