Rails使用before_filter通过GET参数进行身份验证...是否合适?

时间:2013-01-25 21:06:21

标签: ruby-on-rails ruby-on-rails-3 permissions controller

我目前在ApplicationController中有一个before_filter,用于凭据验证。我还希望能够在我直接访问URL时验证用户凭据(即,从脚本而不是从浏览器登录表单/会话)。通过GET请求接受用户凭据是否存在问题?

application_controller.rb

before_filter :login_required

def login_required
    reset_session if session[:last_seen] < Rails.configuration.admin_timeout.minutes.ago rescue nil
    return true if session[:user]
    if (!params[:login].nil? && !params[:password].nil?) && session[:user] = User.authenticate(params[:login], params[:password])
        return true
    else
        render :nothing => true, :status => 401
        return false
    end
    flash[:alert] = 'Please login to continue'
    redirect_to login_url and return false
end

如果这不是一种可接受的做法,我希望只能在某些“安全”的情况下这样做。控制器动作。例如:

product_controller.rb

before_filter :do_something
permit_login_via_get :only => [:index]

def index
    # Do some stuff in here. This should be accessible via http://mydomain.com/products?login=admin&password=yeahlikeidtellyouthat
end

所以现在我的login_requred函数需要修改,以便&#39; permit_login_via_get&#39;方法适用于它。

2 个答案:

答案 0 :(得分:1)

问题是凭据将在URL中传递,因此非常明显,也可能在用户的浏览器历史记录中缓存。

答案 1 :(得分:1)

好的,所以我考虑了一下,并决定最好为我的每个应用程序创建API密钥,并使用Net :: HTTP请求,设置包含API密钥的自定义标头。这样就没有通过URL发送的用户凭据。现在关于这种方法的“安全”与否,或者我需要做些什么才能使其安全是另一回事。但到目前为止,我是如何做到的,它似乎正在起作用:


application.rb(经理申请)

# API Keys
config.api_key = "somelongstringofcharacters"
config.pos_api_key = "anotherlongstringofcharacters"
config.website_api_key = "yetANOTHERlongstringofcharacters"
POS和网站应用程序中的application.rb同样适用于上面的示例。


application_controller.rb(所有应用程序)

before_filter :login_required

def login_required
    reset_session if session[:last_seen] < Rails.configuration.admin_timeout.minutes.ago rescue nil
    return true if session[:user]
        unless request.headers["X-API-Key"].nil?
        if request.headers["X-API-Key"] == Rails.configuration.api_key
            return true
        else
            render :nothing => true, :status => 401
            return false
        end
        end
    flash[:alert] = 'Please login to continue'
    redirect_to :controller => :users, :action => :login
    return false
end

这样所有方法都是私有的(除了那些具有skip_before_filter:login_required的方法)并且如果您通过使用表单使用登录/密码组合登录会话,或者如果您已经做出请求,则可以访问这些方法有一个带有正确应用程序密钥的“X-API-Key”标头。

以下是通过Manager应用程序运行的示例Rake任务;它从POS服务器请求一个受login_required方法保护的JSON文件:

desc "Test Task so that larger projects don't need to be run through"
task :testing => :environment do

    require "net/http"
    require "uri"

    url = URI.parse("http://myposdomain/items.json?all=true&category=Wines")
    req = Net::HTTP::Get.new(url.path)
    req.add_field("X-API-Key", Rails.configuration.pos_api_key)
    res = Net::HTTP.new(url.host, url.port).start do |http|
    http.request(req)
    end
    myposdomain_wines = res.body

end