`
qwlong
  • 浏览: 29720 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

rails 3.0.5 非get 方法 清空session

阅读更多
我使用的rails版本是 3.0.5 的 ,然后使用的是 cookie_session ,现在遇到一个问题:
当我使用admin admin 登录之后,打开其他页面访问session的时候都没有问题,可以访问的到
http://localhost:3000/users/1/roles 这种url也可以访问的到session
但是当我访问以下url的时候
  http://localhost:3000/users/1/roles/1
session 就清空了,我访问不到session中的值了,session中,原来就存了一个session[:user], 不知道是怎么回事

我的路由设置是
  resources :users, :member => { :enable => :put } do
    resources :roles
  end
模仿的是Ruby On Rails 社区网站开发 编写的代码。

后来发现是 所有不是get 请求的都是清空session, put delete 都不行。

由此就奇怪了,然后我就想到要看一下 这个清空session函数 reset_session方法是什么时候有执行过,最后在 rails的gems 包中找到了如下代码:

C:\Ruby187\lib\ruby\gems\1.8\gems\actionpack-3.0.5\lib\action_controller\metal\request_forgery_protection.rb

      # Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
      #
      # Example:
      #
      #   class FooController < ApplicationController
      #     protect_from_forgery :except => :index
      #
      # You can disable csrf protection on controller-by-controller basis:
      #
      #   skip_before_filter :verify_authenticity_token
      #
      # It can also be disabled for specific controller actions:
      #
      #   skip_before_filter :verify_authenticity_token, :except => [:create]
      #
      # Valid Options:
      #
      # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call.  Set which actions are verified.
      def protect_from_forgery(options = {})
        self.request_forgery_protection_token ||= :authenticity_token
        prepend_before_filter :verify_authenticity_token, options
      end
    end

    protected
      # The actual before_filter that is used.  Modify this to change how you handle unverified requests.
      def verify_authenticity_token
        verified_request? || handle_unverified_request
      end

      def handle_unverified_request
        reset_session
      end


    如此便是找到了清空session的罪魁祸首,是因为 rails 的跨域访问问题的解决,所以导致的这个问题, 在rails进行before_filter 之前,要进行 protect_from_forgery 的校验,凡是不是 get请求的,或者是html、javascript请求的都直接清空session,而且不给予你任何提示。 这就是最恶心的地方,3.0.1的时候还是抛异常,如下代码:
      # Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
      #
      # Example:
      #
      #   class FooController < ApplicationController
      #     protect_from_forgery :except => :index
      #
      #     # you can disable csrf protection on controller-by-controller basis:
      #     skip_before_filter :verify_authenticity_token
      #   end
      #
      # Valid Options:
      #
      # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call.  Set which actions are verified.
      def protect_from_forgery(options = {})
        self.request_forgery_protection_token ||= :authenticity_token
        before_filter :verify_authenticity_token, options
      end
    end

    protected

      def protect_from_forgery(options = {})
        self.request_forgery_protection_token ||= :authenticity_token
        before_filter :verify_authenticity_token, options
      end

      # The actual before_filter that is used.  Modify this to change how you handle unverified requests.
      def verify_authenticity_token
        verified_request? || raise(ActionController::InvalidAuthenticityToken)
      end

      # Returns true or false if a request is verified.  Checks:
      #
      # * is the format restricted?  By default, only HTML requests are checked.
      # * is it a GET request?  Gets should be safe and idempotent
      # * Does the form_authenticity_token match the given token value from the params?
      def verified_request?
        !protect_against_forgery? || request.forgery_whitelisted? ||
          form_authenticity_token == params[request_forgery_protection_token]
      end

      # Sets the token value for the current session.
      def form_authenticity_token
        session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32)
      end


因此我找了有一天时间才确认是这个问题

我犹豫不需要跨域访问,所以我采取了最简单的方法,则是把application_controller.rb中的内容 protect_from_forgery 删除掉就可以了,或者使用 skip_before_filter :verify_authenticity_token (还没有试验过),至于以后的跨域访问研究,以后再更新。。。
还要上班呢。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics