为什么 "expiry" header 没有随着 Rails 应用上对 Ruby 的每个新请求而更新?
Why isn't "expiry" header updated with each new request to Ruby on Rails app?
我正在使用 Devise :timeoutable
模块使 session 在闲置一段时间后过期。每个新请求都会重置超时,因此 session 到期日期会发生变化。但这并没有反映在响应客户端的 expiry
header 中。
我注意到 expiry
响应 header 对于我发送到服务器的所有 XHR 都是不变的。即使刷新页面后,expiry
header 也不会更新。换句话说,header 的值仅对我在 sign-in 之后发送的第一个请求是正确的,然后它保持不变。
没有相关代码可以演示,因为 Devise 将 auth header 附加到开箱即用的每个响应。
下面是 响应 headers 的样子:
access-token: qK5XalnvENIXJDHGCKJ5_A
Cache-Control: no-cache
client: c-4_msWmyUFD7PwD7fPW5Q
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Mon, 15 Apr 2019 15:52:32 GMT
expiry: 1556548396
Server: nginx
token-type: Bearer
Transfer-Encoding: chunked
uid: user@email.com
Vary: Origin
X-Request-Id: 2fa70ebf-dcf2-4680-8c25-68d7b5e12b1b
X-Runtime: 0.021004
和请求headers(如果相关):
GET /api/user/context HTTP/1.1
Host: qa.whiz.ai:9060
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
access-token: qK5XalnvENIXJDHGCKJ5_A
client: c-4_msWmyUFD7PwD7fPW5Q
Accept: application/json, text/plain, */*
expiry: 1556548396
uid: user@email.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36
token-type: Bearer
Referer: https://my-page.example.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,uk-UA;q=0.8,uk;q=0.7,ru-UA;q=0.6,ru;q=0.5
Cookie: ...
我尝试从请求 header 中删除 expiry
,但没有任何效果。
这是预期的行为吗? Devise 不应该立即发送 header 中的实际值吗?
我想知道实际的到期时间,以便能够在客户端上执行一些操作。为此,我可以尝试描述 here 的解决方案,但如果我可以利用每个响应中已经存在的 header 会简单得多。
设计超时模块与到期header完全无关。仅仅因为两个概念可能看起来相似并不意味着它们是相关的。
Timeoutable 将 last_request_at
存储在 session 中(默认情况下是 cookie 存储)。
您可以通过以下方式获取值:
ENV['warden'].session(scope)['last_request_at']
其中 scope
基于您的模型名称。
来自the source:
Warden::Manager.after_set_user do |record, warden, options|
scope = options[:scope]
env = warden.request.env
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
options[:store] != false && !env['devise.skip_timeoutable']
last_request_at = warden.session(scope)['last_request_at']
if last_request_at.is_a? Integer
last_request_at = Time.at(last_request_at).utc
elsif last_request_at.is_a? String
last_request_at = Time.parse(last_request_at)
end
proxy = Devise::Hooks::Proxy.new(warden)
if record.timedout?(last_request_at) &&
!env['devise.skip_timeout'] &&
!proxy.remember_me_is_active?(record)
Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
throw :warden, scope: scope, message: :timeout
end
unless env['devise.skip_trackable']
warden.session(scope)['last_request_at'] = Time.now.utc.to_i
end
end
end
过期时间 header 用于控制每个单独响应的缓存。客户端应该如何以及何时考虑指定响应过期的启发式方法非常复杂,但是到期时间 header 包含响应何时应该过期的时间戳。
我正在使用 Devise :timeoutable
模块使 session 在闲置一段时间后过期。每个新请求都会重置超时,因此 session 到期日期会发生变化。但这并没有反映在响应客户端的 expiry
header 中。
我注意到 expiry
响应 header 对于我发送到服务器的所有 XHR 都是不变的。即使刷新页面后,expiry
header 也不会更新。换句话说,header 的值仅对我在 sign-in 之后发送的第一个请求是正确的,然后它保持不变。
没有相关代码可以演示,因为 Devise 将 auth header 附加到开箱即用的每个响应。
下面是 响应 headers 的样子:
access-token: qK5XalnvENIXJDHGCKJ5_A
Cache-Control: no-cache
client: c-4_msWmyUFD7PwD7fPW5Q
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Mon, 15 Apr 2019 15:52:32 GMT
expiry: 1556548396
Server: nginx
token-type: Bearer
Transfer-Encoding: chunked
uid: user@email.com
Vary: Origin
X-Request-Id: 2fa70ebf-dcf2-4680-8c25-68d7b5e12b1b
X-Runtime: 0.021004
和请求headers(如果相关):
GET /api/user/context HTTP/1.1
Host: qa.whiz.ai:9060
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
access-token: qK5XalnvENIXJDHGCKJ5_A
client: c-4_msWmyUFD7PwD7fPW5Q
Accept: application/json, text/plain, */*
expiry: 1556548396
uid: user@email.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36
token-type: Bearer
Referer: https://my-page.example.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,uk-UA;q=0.8,uk;q=0.7,ru-UA;q=0.6,ru;q=0.5
Cookie: ...
我尝试从请求 header 中删除 expiry
,但没有任何效果。
这是预期的行为吗? Devise 不应该立即发送 header 中的实际值吗?
我想知道实际的到期时间,以便能够在客户端上执行一些操作。为此,我可以尝试描述 here 的解决方案,但如果我可以利用每个响应中已经存在的 header 会简单得多。
设计超时模块与到期header完全无关。仅仅因为两个概念可能看起来相似并不意味着它们是相关的。
Timeoutable 将 last_request_at
存储在 session 中(默认情况下是 cookie 存储)。
您可以通过以下方式获取值:
ENV['warden'].session(scope)['last_request_at']
其中 scope
基于您的模型名称。
来自the source:
Warden::Manager.after_set_user do |record, warden, options|
scope = options[:scope]
env = warden.request.env
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
options[:store] != false && !env['devise.skip_timeoutable']
last_request_at = warden.session(scope)['last_request_at']
if last_request_at.is_a? Integer
last_request_at = Time.at(last_request_at).utc
elsif last_request_at.is_a? String
last_request_at = Time.parse(last_request_at)
end
proxy = Devise::Hooks::Proxy.new(warden)
if record.timedout?(last_request_at) &&
!env['devise.skip_timeout'] &&
!proxy.remember_me_is_active?(record)
Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
throw :warden, scope: scope, message: :timeout
end
unless env['devise.skip_trackable']
warden.session(scope)['last_request_at'] = Time.now.utc.to_i
end
end
end
过期时间 header 用于控制每个单独响应的缓存。客户端应该如何以及何时考虑指定响应过期的启发式方法非常复杂,但是到期时间 header 包含响应何时应该过期的时间戳。