Devise中的标准用户列last_sign_in_at
,其中包含更新current_sign_in_at
时的先前值current_sign_in_at
.
是否last_sign_in_at
有设计的核心功能或模块的功能的任何工具,或者只是有一个一般的便利?
我正在尝试从Rails 3中的Warden的after_authenticate回调(在Devise下运行)访问当前会话.
在我的应用程序控制器的顶部,我想做的事情如下:
Warden::Manager.after_authentication do |user,auth,opts|
user.associate_with_ids(session[:pending_ids])
end
Run Code Online (Sandbox Code Playgroud)
最终目标是在注册之前获取存储在会话中的记录ID列表,并在登录后将其与用户模型相关联.
任何帮助将非常感激.
我有一个非常标准的Devise登录程序:
视图:
resource_name,:url => session_path(resource_name))do | f | %><%= f.input :password, input_html: {class: "span6"} %>
<% if devise_mapping.rememberable? -%>
<p><%= f.check_box :remember_me %> Remember me</p>
<% end -%>
<input type="hidden" name="after_sign_in_page" value="<%=@after_sign_in_page%>">
<p><%= f.submit "Sign in", class: "btn btn-success" %></p>
Run Code Online (Sandbox Code Playgroud)
我刚创建了一个sessioncontroller来封装电子邮件:
class SessionsController < Devise::SessionsController
def create
params[:user][:email].downcase!
super
logger.debug "Errors: #{resource.errors}"
end
Run Code Online (Sandbox Code Playgroud)
具有良好凭据的登录很顺利.
使用错误的凭据,它会使用此日志重定向到登录页面:
Started POST "/users/sign_in" for 127.0.0.1 at 2013-01-10 09:59:44 +0100
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"?", "authenticity_token"=>"8eytQkr20JOOOdDvpCWakbmUzNoaHMxK9/BSEVxETik=", "user"=>{"email"=>"nicolas@demoreau.be", "password"=>"[FILTERED]", "remember_me"=>"0"}, "after_sign_in_page"=>"", "commit"=>"Sign in"}
Time zone: …
Run Code Online (Sandbox Code Playgroud) 我有一个使用Devise进行登录的RoR应用程序.创建新用户记录时会执行一些代码,方法是将user.rb文件作为after_create调用/ macro/whatever放入.我需要在每次登录后运行此代码,而不是在新用户创建时运行.
通过一些谷歌搜索,似乎有一个选项是在devise.rb代码中放置Warden回调.我的问题是:
我试图使用Rails应用程序的设计来授予对Rack中间件中的Sinatra应用程序的访问权限.
我的config/routes.rb有:
authenticate "admin" do
mount Admins::Dashboard, :at => "/admins"
end
Run Code Online (Sandbox Code Playgroud)
在我的Sinatra应用程序中,我使用:
before do
env["warden"].authenticate!(:scope => "admin")
end
get "/dashboard" do
erb :dashboard
end
Run Code Online (Sandbox Code Playgroud)
现在,我得到以下stacktrace的错误:
Started GET "/admins/dashboard" for 127.0.0.1 at 2012-10-11 08:45:13 +0200
NoMethodError (undefined method `failure_app' for nil:NilClass):
devise (2.1.2) lib/devise/delegator.rb:11:in `failure_app'
devise (2.1.2) lib/devise/delegator.rb:5:in `call'
warden (1.2.1) lib/warden/manager.rb:130:in `call_failure_app'
warden (1.2.1) lib/warden/manager.rb:116:in `process_unauthenticated'
warden (1.2.1) lib/warden/manager.rb:47:in `call'
actionpack (3.2.8) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.4.1) lib/rack/etag.rb:23:in `call'
rack (1.4.1) lib/rack/conditionalget.rb:25:in `call'
Run Code Online (Sandbox Code Playgroud) 这是一个非常典型的控制器的规范,before_filter
当未登录的用户(也称为访客)尝试访问时,该控制器会重定向到登录页面/projects/new
.
describe ProjectsController do
(...)
describe "GET new" do
context 'when not logged in' do
before { sign_in_nobody }
context 'creating project' do
before { get :new }
it 'denies access' do
expect(response).to be_redirect
end
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
我已经specced访问的所有可能的结果:index
,:show
并:new
为来宾,用户,管理员和superadmins.我没有使用任何记录或访客用户,管理员或没有任何问题 - 但这实际上是这个规范第一次涉及涉及Devise的行动,before_filter :autheticate_user!
并且它在此失败了.
正如你可能已经怀疑的那样 - 规格甚至没有达到expect(response).to be_redirect
,它在之前引发了一个混合:
Failures:
1) ProjectsController GET new when not logged in …
Run Code Online (Sandbox Code Playgroud) 有没有可能修改设备SessionsController进行ajax通信?
我找到了解决方案,并将其发布到答案中,谢谢
我已经设置了带有--api
标志的Rails 5(5.0.0.rc1)应用程序.它使用Warden进行身份验证.
这一切都有效,除了当Warden身份验证失败时,响应未被正确记录.日志看起来像这样:
Started GET "/widgets.json" for ::1 at 2016-06-14 11:38:20 +0000
Processing by WidgetsController#index as JSON
Completed in 0ms (ActiveRecord: 0.0ms)
Run Code Online (Sandbox Code Playgroud)
或者,在生产中:
I, [2016-06-14T14:12:54.938271 #17625] INFO -- : [db39f895-eeb1-4861-91d0-5d52c124e37a] Completed in 1ms (ActiveRecord: 0.0ms)
Run Code Online (Sandbox Code Playgroud)
它当然应该说Completed 401 Unauthorized in...
,但无论出于何种原因,它都不知道响应的状态代码.
Warden身份验证错误被发送到Rack兼容的ActionController::Metal
控制器,非常简单:
class UnauthorizedController < ActionController::Metal
include ActionController::Head
def self.call(env)
@respond ||= action(:respond)
@respond.call(env)
end
def respond
head :unauthorized
end
end
Run Code Online (Sandbox Code Playgroud)
它使用基本head
方法来响应(不需要渲染任何东西),所以可能它的行为与head
在常规Rails控制器中使用的行为相同.但不是.
如果我尝试使用redirect_to ...
或render ...
(包括相关模块之后)也会发生同样的事情.所以在Rack→Rails→Warden→Warden failure app(控制器)的某个地方,响应的状态代码丢失了.日志知道开始记录请求,并知道它已被处理,因为它显然吐出了"已完成..." - …
我试图通过向我发送POST请求来测试某人是否能够登录我的网站SessionsController
.我在几个地方看到过这种推荐方式:
it 'must be able to sign in a user' do
user = create(:user)
post :create, format: :js, user: {email: user.email, password: user.password, remember_me: 0}
assert_response :success
@controller.current_user.must_equal user
end
Run Code Online (Sandbox Code Playgroud)
但这个测试不正确.调用@controller.current_user
将尝试使用已发布的参数对用户进行身份验证,并user
在提供的电子邮件/密码正确时返回.无法保证该create
操作实际上是在调用sign_in
或current_user
.
即使我重新编写测试以检查这些方法是否被调用,也可能会调用其他方法,例如sign_out
.
是否有更明确的方法来最终检查用户是否已登录,如果是,用户是谁?
编辑 -
例如,以下测试将通过
it 'must sign in a user' do
@controller.current_user.must_equal nil
post :create, format: :js, user: {email: @user.email, password: @user.password, remember_me: 0}
assert_response :success
@controller.current_user.must_equal @user
end
Run Code Online (Sandbox Code Playgroud)
当SessionsController #create动作是:
def create
respond_to …
Run Code Online (Sandbox Code Playgroud) 我希望构建一个基于Scalatra的API.其中一项要求是OAuth身份验证.我注意到OAuth的指南尚未在Scalatra官方网站上发布.通过弄清楚如何将基于OAuth的策略添加到Warden中,目前是添加OAuth支持的最佳方式吗?我来自Ruby on Rails的背景,因此很多Scala/Java约定都是新的.可能有几种方法可以解决这个问题,但是我希望有任何解决方案可以在我自己的应用程序中进行实施.