রেলগুলি সিএসআরএফ সুরক্ষা + অ্যাঙ্গুলার.জেএস: রেকর্ড_ফর্ম_ফোরজি আমাকে পোস্টে লগ আউট করতে বাধ্য করে


129

তাহলে protect_from_forgeryবিকল্প application_controller উল্লেখ করা হয়, তারপর আমি লগ ইন করতে পারেন এবং কোন তাহলে GET অনুরোধ সঞ্চালন, কিন্তু খুব প্রথম পোস্ট অনুরোধে রিসেট অধিবেশন, যা আমাকে লগ আউট পাগল।

আমি protect_from_forgeryবিকল্পটি সাময়িকভাবে বন্ধ করে দিয়েছি , তবে Angular.js এর সাহায্যে এটি ব্যবহার করতে চাই। এটি করার কোনও উপায় আছে?


দেখুন এই যদি থাকে, তার সম্পর্কে সেটিং সাহায্য করে HTTP- র হেডার stackoverflow.com/questions/14183025/...
মার্ক Rajcok

উত্তর:


276

আমি মনে করি DOM থেকে সিএসআরএফ-মান পড়া ভাল সমাধান নয়, এটি কেবল একটি কর্মচঞ্চল।

এখানে একটি ডকুমেন্ট ফর্ম কৌনিক জেএস অফিসিয়াল ওয়েবসাইট http://docs.angularjs.org/api/ng.$http :

যেহেতু আপনার ডোমেনে চালিত কেবল জাভাস্ক্রিপ্টই কুকিটি পড়তে পারে, তাই আপনার সার্ভারকে নিশ্চিত করা যেতে পারে যে আপনার ডোমেনে চলছে জাভাস্ক্রিপ্ট থেকে এক্সএইচআর এসেছে।

এর (সিএসআরএফ সুরক্ষা) সুবিধা নিতে আপনার সার্ভারকে প্রথম এইচটিটিপি জিটি অনুরোধে এক্সএসআরএফ-টোকেন নামক একটি জাভাস্ক্রিপ্ট পঠনযোগ্য সেশন কুকিতে একটি টোকেন সেট করতে হবে। পরবর্তীকালে নন-জিইটি অনুরোধের পরে সার্ভারটি যাচাই করতে পারে যে কুকিটি X-XSRF-TOKEN 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

তারপরে, প্রতিটি নন-জিইটি অনুরোধে আমাদের টোকেনটি যাচাই করা উচিত।
যেহেতু রেলগুলি ইতিমধ্যে একই পদ্ধতিটি নিয়ে তৈরি করেছে, তাই আমরা আমাদের যুক্তি যুক্ত করতে কেবল এটিকে ওভাররাইড করতে পারি:

# 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

18
আমি এই কৌশলটি পছন্দ করি, কারণ আপনাকে কোনও ক্লায়েন্ট-সাইড কোডটি পরিবর্তন করতে হবে না।
মিশেল টিলি

11
কীভাবে এই সমাধানটি সিএসআরএফ সুরক্ষার কার্যকারিতা সংরক্ষণ করে? কুকি সেট করে, চিহ্নিত ব্যবহারকারীর ব্রাউজার ক্রস-সাইট অনুরোধগুলি সহ পরবর্তী সমস্ত অনুরোধগুলিতে সেই কুকি প্রেরণ করবে। আমি একটি দূষিত তৃতীয় পক্ষের সাইটটি সেট আপ করতে পারি যা দূষিত অনুরোধ পাঠায় এবং ব্যবহারকারীর ব্রাউজারটি সার্ভারে 'এক্সএসআরএফ-টোকেন' প্রেরণ করবে। দেখে মনে হচ্ছে এই সমাধানটি পুরোপুরি সিএসআরএফ সুরক্ষা বন্ধ করার সমতুল্য।
স্টিভেন

9
কৌনিক ডকগুলি থেকে: "যেহেতু কেবলমাত্র আপনার ডোমেনে চালিত জাভাস্ক্রিপ্টই কুকি পড়তে পারে, তাই আপনার সার্ভারকে নিশ্চিত করা যেতে পারে যে আপনার ডোমেনে চলছে জাভাস্ক্রিপ্ট থেকে এক্সএইচআর এসেছে came" @ স্টেভেন এক্সু - তৃতীয় পক্ষের সাইটটি কীভাবে কুকি পড়বে?
জিমি বেকার

8
@ জিমিবেকার: হ্যাঁ, আপনি ঠিক বলেছেন। আমি ডকুমেন্টেশন পর্যালোচনা করেছি। পদ্ধতির ধারণাটি দৃ sound় হয়। আমি বৈধতার সাথে কুকির সেটিংসকে বিভ্রান্ত করেছিলাম, বুঝতে পারি না যে কৌণিক কাঠামোটি কুকির মানের উপর ভিত্তি করে একটি কাস্টম শিরোনাম স্থাপন করছে!
স্টিভেন

5
form_authenticity_token ails.২ রেলগুলিতে প্রতিটি কলটিতে নতুন মান উত্পন্ন করে, সুতরাং এটি আর কাজ করে না বলে মনে হয়।
ডেভ

78

আপনি যদি ডিফল্ট রেলগুলি সিএসআরএফ সুরক্ষা ( <%= 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');
  }
]);

আপনি যদি পছন্দ করেন তবে নীচের মতো কিছু দিয়ে আপনি কেবল নন-জিইটি অনুরোধে শিরোনাম পাঠাতে পারেন:

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
]

এছাড়াও, হাংওয়াইহইয়ের উত্তরটি পরীক্ষা করে দেখুন , যা ক্লায়েন্টের চেয়ে সার্ভারে থাকা সমস্ত ঘাঁটিগুলি কভার করে।


আমাকে ব্যাখ্যা করতে দাও. বেস ডকুমেন্টটি একটি সরল এইচটিএমএল, না। কারণ আমি ব্যবহার করতে পারি না <%= csrf_meta_tags %>। আমি ভেবেছিলাম যে protect_from_forgeryকেবল উল্লেখ করার জন্য যথেষ্ট হওয়া উচিত । কি করো? বেস ডকুমেন্টটি অবশ্যই একটি সরল এইচটিএমএল হওয়া উচিত (আমি এখানে যিনি বেছে নেন তা নয়)।
পল

3
আপনি যখন protect_from_forgeryযা বলছেন তা যখন ব্যবহার করেন "যখন আমার জাভাস্ক্রিপ্ট কোডটি অ্যাজাক্স অনুরোধ করে, তখন আমি X-CSRF-Tokenশিরোনামটিতে একটি বর্তমান পাঠানোর প্রতিশ্রুতি দিয়ে থাকি যা বর্তমান সিএসআরএফ টোকেনের সাথে মিলে যায়।" এই টোকেনটি <%= csrf_meta_token %>পাওয়ার জন্য, রেলগুলি এটি ডওমের সাথে ইনজেক্ট করে এবং যখনই এটি অ্যাজাক্স অনুরোধ করে তখনই জিকুয়ের সাথে মেটা ট্যাগের সামগ্রী পেয়ে যায় (ডিফল্ট রেলস 3 ইউজেএস ড্রাইভার এটি আপনার জন্য করে)। যদি আপনি ইআরবি ব্যবহার না করে থাকেন তবে পৃষ্ঠাগুলি এবং / অথবা জাভাস্ক্রিপ্টে রেলগুলি থেকে বর্তমান টোকেন পাওয়ার কোনও উপায় নেই - এবং এইভাবে আপনি protect_from_forgeryএই পদ্ধতিতে ব্যবহার করতে পারবেন না ।
মিশেল টিলি

ব্যাখ্যার জন্য ধন্যবাদ। আমি কী ভেবেছিলাম যে ক্লাসিক সার্ভার-সাইড অ্যাপ্লিকেশনটিতে ক্লায়েন্ট পক্ষ csrf_meta_tagsপ্রতিটি সময় সার্ভারের প্রতিক্রিয়া উত্পন্ন করে এবং প্রতিবার এই ট্যাগগুলি পূর্বেরগুলির চেয়ে পৃথক। সুতরাং, এই ট্যাগগুলি প্রতিটি অনুরোধের জন্য অনন্য। প্রশ্নটি হল: অ্যাপ্লিকেশন কীভাবে একটি এজেএক্স অনুরোধের জন্য (কৌনিক ছাড়াই) এই ট্যাগগুলি গ্রহণ করে? আমি jQuery পোষ্ট অনুরোধের সাথে সুরক্ষা_ফ্রম_ফোর্জি ব্যবহার করেছি, এই সিএসআরএফ টোকেন পেয়ে নিজেকে কখনও বিরক্ত করিনি এবং এটি কার্যকর হয়েছে। কিভাবে?
পল

1
রেলস ইউজেএস ড্রাইভারটি jQuery.ajaxPrefilterএখানে প্রদর্শিত হিসাবে ব্যবহার করে : github.com/indirect/jquery-rails/blob/c1eb6ae/vendor/assets/… আপনি এই ফাইলটি ব্যবহার করতে পারেন এবং সমস্ত হুপস রেলগুলি ঝাঁপিয়ে পড়ে দেখতে পারেন এটির কাজটি বেশ কার্যকরভাবে তৈরি করতে pretty এটার ব্যাপারে দুশ্চিন্তা কর.
মিশেল টিলি

@ ব্র্যান্ডনটিলি এটি কি কেবল চালানো putও চালিয়ে যাওয়ার postবদলে বোঝায় common? থেকে পাগল নিরাপত্তা নির্দেশিকা :The solution to this is including a security token in non-GET requests
christianvuerings

29

Angular_rails_csrf মণি স্বয়ংক্রিয়ভাবে প্যাটার্ন বর্ণিত জন্য সমর্থন যোগ করা HungYuHei এর উত্তর আপনার সব কন্ট্রোলার হবে:

# Gemfile
gem 'angular_rails_csrf'

অ্যাঙ্গুলার_রেইস_সিএসআরএফ সঠিকভাবে ব্যবহার করার জন্য আপনার অ্যাপ্লিকেশন কন্ট্রোলার এবং অন্যান্য সিএসআরএফ / জালিয়াতি সম্পর্কিত সেটিংস কীভাবে কনফিগার করা উচিত তা সম্পর্কে কোনও ধারণা?
বেন হুইলার 21

এই মন্তব্যের সময় angular_rails_csrfরত্নটি 5 টি রেলগুলির সাথে কাজ করে না However তবে, সিএসআরএফ মেটা ট্যাগের মান সহ কৌনিক অনুরোধ শিরোনাম কনফিগার করছে!
বিডোয়েগো


4

পূর্ববর্তী সমস্ত উত্তরগুলিকে একত্রিত করে এমন উত্তর এবং এটি নির্ভর করে যে আপনি Deviseপ্রমাণীকরণ রত্ন ব্যবহার করছেন ।

প্রথমত, রত্নটি যুক্ত করুন:

gem 'angular_rails_csrf'

এরপরে, প্রয়োগ_কন্ট্রোলআরআরবিতে 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')

1
আপনি কেন $injectorসরাসরি ইনজেকশনের পরিবর্তে ইনজেকশন দিচ্ছেন $http?
হোয়াইটহ্যাট 101

এটি কাজ করে, তবে কেবলমাত্র অনুরোধটি ইতিমধ্যে পুনরাবৃত্তি হয়েছে কিনা তা আমি কেবল যাচাই করে দেখি। যখন এটি পুনরাবৃত্তি হয়েছিল তখন আমরা আর প্রেরণ করি না কারণ এটি চিরকালের জন্য লুপ হয়ে যাবে।
duleorlovic

1

আমি অন্যান্য উত্তরগুলি দেখেছি এবং সেগুলি দুর্দান্ত এবং সুচিন্তিত বলে মনে করেছি। আমি আমার রেলস অ্যাপ্লিকেশনটি কাজ করেছিলাম যদিও আমি যা মনে করি এটি একটি সহজ সমাধান হিসাবে কাজ করেছিলাম তাই আমি ভেবেছিলাম ভাগ করব। আমার রেল অ্যাপ্লিকেশনটি এতে এতে খেলাপি হয়ে গেছে,

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

আমি মন্তব্যগুলি পড়েছি এবং মনে হয়েছিল যে এটিই আমি কৌনিক ব্যবহার করতে এবং সিএসআরএফ ত্রুটি এড়াতে চাই। আমি এটি এটিকে পরিবর্তন করেছি,

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
আপনি যদি রেল 'সেশন' ব্যবহার করার চেষ্টা করছেন তবে এটি সমস্যার কারণ হয়ে দাঁড়াবে যেহেতু এটি জালিয়াতির পরীক্ষায় ব্যর্থ হয় যদি তা বাতিল হয়ে যায়, যা আপনি সর্বদা থাকবেন, যেহেতু আপনি ক্লায়েন্টের পক্ষ থেকে সিএসআরএফ-টোকেন প্রেরণ করছেন না।
হাজপুজ

তবে আপনি যদি রেল সেশনগুলি ব্যবহার না করেন তবে সব ঠিক আছে; ধন্যবাদ! আমি এর পরিষ্কার সমাধান খুঁজে পেতে লড়াই করে যাচ্ছি।
মরগান 21

1

আমি আমার অ্যাপ্লিকেশনটিতে হাংওয়াইইইয়ের উত্তর থেকে সামগ্রীটি ব্যবহার করেছি। আমি দেখতে পেয়েছি যে আমি কয়েকটি অতিরিক্ত সমস্যা নিয়ে কাজ করছি, কিছু আমার প্রমাণীকরণের জন্য ডিভাইস ব্যবহার করার কারণে, এবং কিছু আমার অ্যাপ্লিকেশনটির সাথে পাওয়া ডিফল্ট কারণে:

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

1

আমি এটি একটি খুব দ্রুত হ্যাক পেয়েছি। আমাকে যা করতে হয়েছিল তা হ'ল:

ক। আমার দৃষ্টিতে, আমি একটি $scopeপরিবর্তনশীল সূচনা করি যার মধ্যে টোকেন থাকে, আসুন ফর্মের আগে বলা যাক, বা নিয়ামক সূচনাতে আরও ভাল:

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

খ। আমার অ্যাংুলারজেএস কন্ট্রোলারে আমার নতুন এন্ট্রিটি সংরক্ষণ করার আগে, আমি হ্যাশটিতে টোকেন যুক্ত করছি:

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

আর কিছু করার দরকার নেই।


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

এটি কৌণিক দিক নিয়ে কাজ করছে!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.