Rails 3禁用会话cookie

And*_*sov 26 ruby cookies session ruby-on-rails ruby-on-rails-3

我在RoR 3上编写了RESTful API.我必须让我的应用程序不发送"Set-Cookie header"(客户端使用auth_token参数授权).

我试过用session :off,reset_session但没有任何意义.我devise用作身份验证框架.

这是我的ApplicationController

class ApplicationController < ActionController::Base
  before_filter :reset_session #, :unless => :session_required?
  session :off #, :unless => :session_required?

  skip_before_filter :verify_authenticity_token
  before_filter :access_control_headers!

  def options
    render :text => ""
  end

  private
  def access_control_headers!
    response.headers["Access-Control-Allow-Origin"] = "*"
    response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
    response.headers["Access-Control-Allow-Credentials"] = "true"
    response.headers["Access-Control-Allow-Headers"] = "Content-type"
  end

  def session_required?
    !(params[:format] == 'xml' or params[:format] == 'json')
  end
end
Run Code Online (Sandbox Code Playgroud)

Dar*_*win 39

使用内置选项.

env['rack.session.options'][:skip] = true
Run Code Online (Sandbox Code Playgroud)

或等同物

request.session_options[:skip] = true
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到它的文档http://doc.rubyists.com/rack/Rack/Session/Abstract/ID.html

  • 谢谢.这很简单而且非常有效.在我的会话控制器中用于json请求的before_action (2认同)

Rya*_*arn 34

正如John对答案的评论中所提到的,清除会话不会阻止会话cookie被发送.如果您希望完全删除cookie,则必须使用Rack中间件.

class CookieFilter
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)

    # use only one of the next two lines

    # this will remove ALL cookies from the response
    headers.delete 'Set-Cookie'
    # this will remove just your session cookie
    Rack::Utils.delete_cookie_header!(headers, '_app-name_session')

    [status, headers, body]
  end
end
Run Code Online (Sandbox Code Playgroud)

通过使用以下主体创建初始化程序来使用它:

Rails.application.config.middleware.insert_before ::ActionDispatch::Cookies, ::CookieFilter
Run Code Online (Sandbox Code Playgroud)

为了防止cookie过滤器最终出现在应用程序堆栈跟踪中,有时可能会让人感到困惑,您可能希望在回溯中将其静音(假设您将其放入lib/cookie_filter.rb):

Rails.backtrace_cleaner.add_silencer { |line| line.start_with? "lib/cookie_filter.rb" }
Run Code Online (Sandbox Code Playgroud)

  • 我意识到这是一个旧的评论,但更改initializers/session_store.rb以包含:'PlayreadyLicense :: Application.config.session_store:disabled`以禁用会话cookie有什么问题? (2认同)

asg*_*eo1 8

我不确定他们何时将它添加到Devise中,但似乎有一个配置可以让你在使用auth_token时禁用会话cookie的发送:

# By default Devise will store the user in session. You can skip storage for
# :http_auth and :token_auth by adding those symbols to the array below.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing :skip => :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth, :token_auth]
Run Code Online (Sandbox Code Playgroud)

它运作良好.我遇到的唯一问题是我仍然需要能够向token_controller发出初始请求以生成/检索令牌.即POST /api/v1/tokens.json,遗憾的是会导致为该请求返回会话cookie.

所以我最终实现了CookieFilterRyan Ahearn上面写的初始化器.

此外,由于我的应用程序同时具有Web前端和JSON API,我只想过滤JSON api的cookie.所以我修改了CookieFilter类,首先检查属于api的请求:

if env['PATH_INFO'].match(/^\/api/)
  Rack::Utils.delete_cookie_header!(headers, '_myapp_session')
end
Run Code Online (Sandbox Code Playgroud)

不确定是否有更好的方法...


tom*_*eng 5

另一种解决方案:在控制器中你想避免使用cookies,添加:

after_filter :skip_set_cookies_header

def skip_set_cookies_header
  request.session_options = {}
end
Run Code Online (Sandbox Code Playgroud)

如果你有一组api控制器,在api_controller类中设置它,让你的其他控制器继承api_controller.

由于会话opts为空,因此跳过设置Set-Cookie标头.