Rails ActiveRecord存储和新会话 [英] Rails ActiveRecord store and new session

查看:124
本文介绍了Rails ActiveRecord存储和新会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Rails的新手,遇到一个奇怪的问题,我不明白。
我使用ActiveRecord作为会话存储,并需要添加会话ID作为所有请求的JSON响应的属性。我使用Devise以及如果它有一些影响的情况。问题是,如果用户没有cookie(或者至少没有cookie中的会话ID)的请求,session.id是空的或 - 注意,请 - 不是在响应cookie中设置的相同的值。 / p>

对于调试,我将此代码作为after_filter添加到ApplicationController:

  puts session.id 
puts request.session_options [:id]

相同。它们匹配cookie中的值(如果存在)。



我的意见是,session_id在实际保存后获得新的值到数据库,它必须是唯一的。 DB迁移:

  def change 
create_table:sessions do | t |
t.string:session_id,:null => false
t.text:data
t.timestamps
end

add_index:sessions,:session_id,:unique => true
add_index:sessions,:updated_at
end

我的问题:我在获得第一个响应之前获得了新会话的实际session.id值?



UPD:



我刚刚创建了一个新的Rails应用程序,使用没有Devise的ActiveRecord会话存储,我可以得到session.id,它将在响应此代码id应用程序控制器之前在cookie中设置:

  class ApplicationController< ActionController :: Base 
after_filter:show_session

def show_session
puts session.id
end
end

但是在我使用Devise的现有应用程序中,我获得的值实际上看起来像会话ID,但不匹配cookie中设置的值通过Set-Cookie响应头和实际保存到数据库中的会话表的值。看起来Devise与ActiveRecord会话存储有某种冲突。需要更深入地了解。



UPD 2



我发现问题根源。正如我所说,我使用Devise授权Omniauth。根据文档,sign_in方法为了安全原因重置会话ID。但是之后重置session.id返回的旧值,已经自动设置。我使用此代码作为Omniauth回调:

  def facebook_access_token 
sign_in @user
puts session.id
end



在控制台中我获得的会话ID不同于Set- Cookie响应标头。如果我注释sign_in行,这些值匹配。新问题:如何在sign_in方法中重置之后获取新的会话id值?

解决方案

我遇到的问题是由默认的Warden配置引起的。它更新了会话ID,但不知何故新的ID不能通过session.id访问。



我发现阻止此行为的唯一方法是将此代码放入config / initializers / devise.rb:

  Warden :: Manager.after_set_user do | user,auth,opts | 
auth.env [rack.session.options] [:renew] = false
end


b $ b

可能这个方法不是真的好安全的原因,但我没有其他的想法在一周的搜索和阅读源。


I am new to Rails and experience a strange issue I don't understand. I use ActiveRecord as a session store and need to add session id as a property of JSON responses for all the requests. I use Devise as well if it have some impact on the situation. The problem is that if a request is made by a user without cookies (or at least without session id in the cookie) the session.id is empty or - attention, please - not the same value that is set in the response cookie.

For debugging, I add this code as an after_filter to ApplicationController:

puts session.id
puts request.session_options[:id]

Both values are the same. They match the value in the cookie if it is present. Otherwise, if session id is not present in the cookie, the cookie set after that request has different value.

My opinion is that session_id gets new value after it is actually saved to the database, where it have to be unique. DB migration:

def change
  create_table :sessions do |t|
    t.string :session_id, :null => false
    t.text :data
    t.timestamps
  end

  add_index :sessions, :session_id, :unique => true
  add_index :sessions, :updated_at
end

My question: How can I get the actual session.id value of a new session before the first response is rendered?

UPD:

I just created a new Rails app that uses ActiveRecord session store without Devise, and I can get session.id that is going to be set in cookie just before response with this code id application controller:

class ApplicationController < ActionController::Base
  after_filter :show_session

  def show_session
    puts session.id
  end
end

But in my existing app with Devise I get a value that really looks like a session id, but that doesn't match the value set in the cookie via Set-Cookie response header and the value actually saved to sessions table in database. Looks like Devise have a conflict with ActiveRecord session store in some way. Need to go deeper to figure it out.

UPD 2

Looks like I found the problem roots. As I said, I use Devise for authorization with Omniauth. According to the documentation, sign_in method resets session id for security reasons. But after that reset session.id returns the old value, that had been automatically set. I use this code as an Omniauth callback:

def facebook_access_token
  sign_in @user
  puts session.id
end

And in console I get session id different from the one set in the Set-Cookie response header. If I comment "sign_in" line, these values match. New question: how can I get the new session id value after it is been reset inside of sign_in method? Is it an internal Warden/Devise implementation or something?

解决方案

The problem I experienced was caused by default Warden configuration. It renewed session id, but somehow the new id was not accessible via session.id.

The only way I found to stop this behavior was putting this code into config/initializers/devise.rb:

Warden::Manager.after_set_user do |user,auth,opts|
  auth.env["rack.session.options"][:renew] = false
end

Probably this method is not really good for security reasons, but I have no other ideas in a week of searching and reading sources.

这篇关于Rails ActiveRecord存储和新会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆