[英]skip_before_filter :authenticate_user! does not work for AJAX call
I have a controller: 我有一个控制器:
class SessionTimeoutController < ApplicationController
# snip
skip_before_filter :authenticate_user!, only: [:has_user_timed_out]
#snip
# Determines whether the user has been logged out due to
# inactivity or not.
def has_user_timed_out
@has_timed_out = (!user_signed_in?) or (current_user.timedout? (user_session["last_request_at"]))
respond_to do |format|
format.json { render json: @has_timed_out, status: :created}
end
end
#snip
end
I send a request to session_timeout/has_user_timed_out
using AJAX: 我使用AJAX向
session_timeout/has_user_timed_out
发送请求:
$.ajax({
url: '/session_timeout/has_user_timed_out',
type: 'GET',
dataType: 'json',
success: function( logged_out ) {
if(logged_out === true)
{
window.location = '/users/sign_in?timedout=1'
}
else
{
checkTimeLeft();
}
}
});
When this AJAX call is made, I expect it to always get a response, even if the user logged out. 进行此AJAX调用后,即使用户注销,我希望它始终会得到响应。 I expect this because I set
skip_before_filter :authenticate_user!
我期望如此,因为我设置了
skip_before_filter :authenticate_user!
in the controller. 在控制器中。 However, when I send the AJAX, the server sends back a
401 Unauthorized
response. 但是,当我发送AJAX时,服务器会发回
401 Unauthorized
响应。 Why is this? 为什么是这样?
Moreover, when I run this JS from the browser console, it works as expected. 此外,当我从浏览器控制台运行此JS时,它会按预期工作。 The only time I have a problem with my AJAX is when it's called from the view.
我的AJAX唯一的问题是从视图中调用它时。
$.ajax({url: '/session_timeout/has_user_timed_out', type: 'GET', dataType:'JSON', success: function(logged_out) {console.log(logged_out + ' ' + typeof logged_out);}});
One thing that could be causing the problems is that I send the AJAX request within a split-second of the user being automatically logged out due to inactivity. 可能引起问题的一件事是,我在由于不活动而自动注销的用户瞬间就发送了AJAX请求。 Would this confuse Devise at all?
这会完全混淆Devise吗?
EDIT: This is my Rails log when I send a request that results in a 401 response: 编辑:这是我发送导致401响应的请求时的Rails日志:
Started GET "/session_timeout/has_user_timed_out" for 10.0.2.2 at 2013-07-25 21:25:51 +0000
Processing by SessionTimeoutController#has_user_timed_out as JSON
ConfigVar Load (0.2ms) SELECT `config_vars`.* FROM `config_vars` WHERE `config_vars`.`name` = 'maintenance_mode' ORDER BY `config_vars`.`id` ASC LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 14 ORDER BY `users`.`id` ASC LIMIT 1
Completed 401 Unauthorized in 4ms
This is my Rails log when I send a request that works, even though the user is logged out: 即使用户已注销,当我发送有效的请求时,这也是我的Rails日志:
Started GET "/session_timeout/has_user_timed_out" for 10.0.2.2 at 2013-07-25 21:29:39 +0000
Processing by SessionTimeoutController#has_user_timed_out as JSON
ConfigVar Load (0.1ms) SELECT `config_vars`.* FROM `config_vars` WHERE `config_vars`.`name` = 'maintenance_mode' ORDER BY `config_vars`.`id` ASC LIMIT 1
Completed 201 Created in 3ms (Views: 0.1ms | ActiveRecord: 0.1ms)
Playing around with it some more, it looks like the first time I send a request to session_timeout/has_user_timed_out
after the user has been logged out, it fails, no matter how long I wait. session_timeout/has_user_timed_out
,它看起来就像我在用户session_timeout/has_user_timed_out
后第一次向session_timeout/has_user_timed_out
发送请求时,无论我等待多长时间,它都会失败。 Then, all subsequent requests succeed. 然后,所有后续请求成功。
I found a workaround. 我找到了解决方法。
$.ajax
can take a status
option that lets you intercept server responses based on their response codes. $.ajax
可以使用status
选项,该选项使您可以根据服务器的响应代码来拦截服务器响应。 In my case, what I care about is whether the user is logged in. A 401
error tells me that the user is logged out, so I can intercept the response and act accordingly: 就我而言,我关心的是用户是否已登录
401
错误告诉我用户已注销,因此我可以截取响应并采取相应的措施:
$.ajax({
url: '/session_timeout/has_user_timed_out',
type: 'GET',
dataType: 'json',
success: function( logged_out ) {
if(logged_out === true)
{
window.location = '/users/timedout'
}
else
{
checkTimeLeft();
}
},
// THIS IS THE CODE I ADDED FOR MY WORKAROUND:
statusCode: {
// If we get back an authentication error, it's a
// pretty safe bet we're not logged in anymore
401: function() {
window.location = '/users/timedout'
}
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.