【问题标题】:Rails : Devise with config.session_store :disabledRails:使用 config.session_store 进行设计:禁用
【发布时间】:2013-05-14 21:44:50
【问题描述】:

我正在使用 Rails 3 和 gem devise 构建一个无状态的 RESTful API。

由于我不想存储任何会话,因此我通过在 config/initializers/session_store.rb 中定义来禁用它们:

MyApp::Application.config.session_store :disabled

我所有的 Warden Strategies(http 基本身份验证、令牌身份验证)都不存储任何信息(stored? 返回 false)。

我在我的控制器中使用助手 authenticate_user! 作为 before_filter。我在认证过程中收到以下错误:

NoMethodError (undefined method `[]' for nil:NilClass) :
warden (1.2.1) lib/warden/session_serializer.rb:32:in `fetch'
warden (1.2.1) lib/warden/proxy.rb:212:in `user'
warden (1.2.1) lib/warden/proxy.rb:318:in `_perform_authentication'    
warden (1.2.1) lib/warden/proxy.rb:127:in `authenticate!'
devise (2.2.3) lib/devise/controllers/helpers.rb:48:in `authenticate_user!'

第 32 行 session_serializer 中的代码如下:

def fetch(scope)
  key = session[key_for(scope)] # it crashes here
  return nil unless key

  method_name = "#{scope}_deserialize"
  user = respond_to?(method_name) ? send(method_name, key) : deserialize(key)
  delete(scope) unless user
  user
end

它崩溃是因为session(即@env['rack.sessions'])等于nil(session_store 确实被禁用)。这是默认调用,尚未调用策略。

由于我不想修补补丁,我正在寻找一种在禁用 session_store 的情况下实现此目的的好方法。

谢谢

【问题讨论】:

  • 您使用设计而不是简单的http身份验证的任何原因?根据我的经验,无状态 API 的设计太过分了。
  • @eabraham : 我使用了几个相当实用的设计模块(:database_authenticatable、:registerable、:validatable、:recoverable、:token_authenticatable)。

标签: ruby-on-rails session devise warden


【解决方案1】:

如果您愿意放弃设计,我建议您使用令牌进行身份验证。可以在 Rails 中快速设置令牌身份验证,并通过将令牌传递到每个请求标头来验证请求。

授权:Token token="xxx"

如果您有兴趣,我已经添加了我的默认 Rails api 令牌身份验证代码。

class ApplicationController < ActionController::Base
  protect_from_forgery


  private
  def restrict_access
    authenticate_with_http_token do |token, options|
      User.exists?(authentication_token: token)
    end
  end

  private
  def api_user
    authenticate_with_http_token do |token, options|
      User.find_by_authentication_token(token)
    end
  end
end

class UsersController < ApplicationController
  before_filter :restrict_access, :except => ['create']

  def create
    user=User.create(:email=>params[:email],
                     :password=>params[:password],
                     :password_confirmation=>params[:password_confirmation])

  end
end

class TokensController < ApplicationController
  respond_to :json

  def create
  user = User.authenticate(params[:email],params[:password])
  if user
    render :json => User.find_by_email(params[:email])
  else
    render :json => "#{params[:email]} not authorized.", :status => 401
  end
end

class User < ActiveRecord::Base

  attr_accessible :email, :authentication_token
  attr_accessor :password, :password_confirmation

  def self.authenticate(email, password)
    user= find_by_email(email)
    user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt) ? user : nil
  end
  private
  def generate_authentication_token
    begin
      self.authentication_token = SecureRandom.hex
    end while self.class.exists?(authentication_token: authentication_token)
    self.last_sign_in_at=DateTime.now
    self.sign_in_count=self.sign_in_count+1
  end

  private
  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password,password_salt)
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    相关资源
    最近更新 更多