복붙노트

[RUBY-ON-RAILS] CSRF 보호 + Angular.js는 레일 : protect_from_forgery가 POST에 로그 아웃 나를 수 있습니다

RUBY-ON-RAILS

CSRF 보호 + Angular.js는 레일 : protect_from_forgery가 POST에 로그 아웃 나를 수 있습니다

protect_from_forgery 옵션이 application_controller에 언급 된 경우, 나는 로그인 및 GET 요청을 수행하지만, 첫 번째 POST 요청에 리셋 나를 로그 아웃 세션을, 레일 수 있습니다.

나는 일시적으로 떨어져 protect_from_forgery 옵션을 설정하지만, Angular.js와 함께 사용하고 싶습니다. 그렇게 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.나는 DOM에서 CSRF 값을 읽는 것은 그냥 해결의 좋은 솔루션하지 생각합니다.

    나는 DOM에서 CSRF 값을 읽는 것은 그냥 해결의 좋은 솔루션하지 생각합니다.

    여기에 문서 양식 AngularJS와 공식 웹 사이트 http://docs.angularjs.org/api/ng.$http입니다 :

    다음은 그 지침에 따라 내 솔루션입니다 :

    첫째, 쿠키를 설정 :

    # app/controllers/application_controller.rb
    
    # Turn on request forgery protection
    protect_from_forgery
    
    after_action :set_csrf_cookie
    
    def set_csrf_cookie
      cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
    end
    

    그런 다음, 우리는 모든 비 GET 요청에 토큰을 확인해야합니다. 레일 이미 비슷한 방법으로 내장되어 있기 때문에, 우리는 단지 우리의 논리를 추가 할을 재정의 할 수 있습니다 :

    # app/controllers/application_controller.rb
    
    protected
    
      # In Rails 4.2 and above
      def verified_request?
        super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
      end
    
      # In Rails 4.1 and below
      def verified_request?
        super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
      end
    
  2. ==============================

    2.기본 레일 CSRF 보호를 (<% = csrf_meta_tags %>)를 사용하는 경우,이처럼 각도 모듈을 구성 할 수 있습니다 :

    기본 레일 CSRF 보호를 (<% = csrf_meta_tags %>)를 사용하는 경우,이처럼 각도 모듈을 구성 할 수 있습니다 :

    myAngularApp.config ["$httpProvider", ($httpProvider) ->
      $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
    ]
    

    또는, 커피 스크립트를 (무엇을!?)를 사용하지 않는 경우 :

    myAngularApp.config([
      "$httpProvider", function($httpProvider) {
        $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
      }
    ]);
    

    당신이 원하는 경우에만 다음과 같은 비 - GET 요청에 헤더를 보낼 수 있습니다 :

    myAngularApp.config ["$httpProvider", ($httpProvider) ->
      csrfToken = $('meta[name=csrf-token]').attr('content')
      $httpProvider.defaults.headers.post['X-CSRF-Token'] = csrfToken
      $httpProvider.defaults.headers.put['X-CSRF-Token'] = csrfToken
      $httpProvider.defaults.headers.patch['X-CSRF-Token'] = csrfToken
      $httpProvider.defaults.headers.delete['X-CSRF-Token'] = csrfToken
    ]
    

    또한, 서버가 아닌 클라이언트의 모든 기지를 커버 HungYuHei의 답변을, 체크 아웃해야합니다.

  3. ==============================

    3.angular_rails_csrf 보석 자동으로 모든 컨트롤러에 HungYuHei의 대답에 설명 된 패턴에 대한 지원을 추가합니다 :

    angular_rails_csrf 보석 자동으로 모든 컨트롤러에 HungYuHei의 대답에 설명 된 패턴에 대한 지원을 추가합니다 :

    # Gemfile
    gem 'angular_rails_csrf'
    
  4. ==============================

    4.이전의 모든 답변을 병합 대답은 그것을 당신이 고안 인증 보석을 사용하고 있는지 의존한다.

    이전의 모든 답변을 병합 대답은 그것을 당신이 고안 인증 보석을 사용하고 있는지 의존한다.

    우선, 보석을 추가 :

    gem 'angular_rails_csrf'
    

    다음으로, application_controller.rb에 rescue_from 블록을 추가 :

    protect_from_forgery with: :exception
    
    rescue_from ActionController::InvalidAuthenticityToken do |exception|
      cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
      render text: 'Invalid authenticity token', status: :unprocessable_entity
    end
    

    그리고 마지막으로, 당신에게 각 응용 프로그램을 인터셉터 모듈을 추가 할 수 있습니다.

    # coffee script
    app.factory 'csrfInterceptor', ['$q', '$injector', ($q, $injector) ->
      responseError: (rejection) ->
        if rejection.status == 422 && rejection.data == 'Invalid authenticity token'
            deferred = $q.defer()
    
            successCallback = (resp) ->
              deferred.resolve(resp)
            errorCallback = (resp) ->
              deferred.reject(resp)
    
            $http = $http || $injector.get('$http')
            $http(rejection.config).then(successCallback, errorCallback)
            return deferred.promise
    
        $q.reject(rejection)
    ]
    
    app.config ($httpProvider) ->
      $httpProvider.interceptors.unshift('csrfInterceptor')
    
  5. ==============================

    5.나는 다른 답변을보고 그들이 큰했고 잘 생각 생각했다. 나는 레일 내가 공유하고자 그래서 나는 간단한 해결책을 무슨 생각으로하지만 용 앱 얻었다. 이 그것에서 기본값으로 내 레일 응용 프로그램은, 온

    나는 다른 답변을보고 그들이 큰했고 잘 생각 생각했다. 나는 레일 내가 공유하고자 그래서 나는 간단한 해결책을 무슨 생각으로하지만 용 앱 얻었다. 이 그것에서 기본값으로 내 레일 응용 프로그램은, 온

    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      protect_from_forgery with: :exception
    end
    

    나는 의견을 읽고 그것이 내가 각도 사용하고 CSRF 오류를 방지 할 것입니다처럼 보였다. 나는이로 변경

    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      protect_from_forgery with: :null_session
    end
    

    그리고 지금은 작동한다! 나는이 일을 안 어떤 이유가 표시되지 않습니다,하지만 난 다른 포스터에서 몇 가지 통찰력을 듣고 싶네요.

  6. ==============================

    6.내 응용 프로그램에 HungYuHei의 대답에서 콘텐츠를 사용했습니다. 나는 몇 가지 이유로 인증을 위해 고안 내 사용의, 그러나 몇 가지 추가 문제를 다루는 것을 발견, 때문에 내 응용 프로그램과 함께 가지고하는 기본 중 일부 :

    내 응용 프로그램에 HungYuHei의 대답에서 콘텐츠를 사용했습니다. 나는 몇 가지 이유로 인증을 위해 고안 내 사용의, 그러나 몇 가지 추가 문제를 다루는 것을 발견, 때문에 내 응용 프로그램과 함께 가지고하는 기본 중 일부 :

    protect_from_forgery with: :exception
    

    나는 관련 스택 오버플로 질문이 답변을주의, 그리고 다양한 고려 사항을 요약 훨씬 더 블로그 자세한 글을 썼다. 애플리케이션 제어기 여기 관련된 것을 용액의 부분 :

      protect_from_forgery with: :exception
    
      after_filter :set_csrf_cookie_for_ng
    
      def set_csrf_cookie_for_ng
        cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
      end
    
      rescue_from ActionController::InvalidAuthenticityToken do |exception|
        cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
        render :error => 'Invalid authenticity token', {:status => :unprocessable_entity} 
      end
    
    protected
      def verified_request?
        super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
      end
    
  7. ==============================

    7.나는이에 매우 빠른 해킹을 발견했다. 모든 내가해야 할 일을했을 다음과 같다 :

    나는이에 매우 빠른 해킹을 발견했다. 모든 내가해야 할 일을했을 다음과 같다 :

    ㅏ. 내보기에, 내가 토큰을 포함하는 $ 범위 변수를 초기화의 양식 전에, 또는 더 나은 컨트롤러 초기화시 가정 해 봅시다 :

    <div ng-controller="MyCtrl" ng-init="authenticity_token = '<%= form_authenticity_token %>'">
    

    비. 내 AngularJS와 컨트롤러에서 내 새 항목을 저장하기 전에, 나는 해시에 토큰을 추가 :

    $scope.addEntry = ->
        $scope.newEntry.authenticity_token = $scope.authenticity_token 
        entry = Entry.save($scope.newEntry)
        $scope.entries.push(entry)
        $scope.newEntry = {}
    

    더 아무것도 할 필요가 없습니다.

  8. ==============================

    8.

     angular
      .module('corsInterceptor', ['ngCookies'])
      .factory(
        'corsInterceptor',
        function ($cookies) {
          return {
            request: function(config) {
              config.headers["X-XSRF-TOKEN"] = $cookies.get('XSRF-TOKEN');
              return config;
            }
          };
        }
      );
    

    그것은 AngularJS와 측면에 일하고있어!

  9. from https://stackoverflow.com/questions/14734243/rails-csrf-protection-angular-js-protect-from-forgery-makes-me-to-log-out-on by cc-by-sa and MIT license