Rails: kan de authenticiteit van het CSRF-token niet verifiëren bij het maken van een POST-verzoek

Ik wil een POST requestdoen aan mijn lokale ontwikkelaar, als volgt:

 HTTParty.post('http://localhost:3000/fetch_heroku',
                :body => {:type => 'product'},)

Vanaf de serverconsole rapporteert het echter

Started POST "/fetch_heroku" for 127.0.0.1 at 2016-02-03 23:33:39 +0800
  ActiveRecord::SchemaMigration Load (0.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by AdminController#fetch_heroku as */*
  Parameters: {"type"=>"product"}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms

Hier is mijn configuratie van de controller en routes, het is vrij eenvoudig.

 def fetch_heroku
    if params[:type] == 'product'
      flash[:alert] = 'Fetch Product From Heroku'
      Heroku.get_product
    end
  end
  post 'fetch_heroku' => 'admin#fetch_heroku'

Ik weet niet zeker wat ik moet doen? De CSRF uitschakelen zou zeker werken, maar ik denk dat het mijn fout zou moeten zijn bij het maken van zo’n API.

Is er nog een andere instelling die ik moet doen?


Antwoord 1, autoriteit 100%

Cross-site request forgery (CSRF/XSRF) is wanneer een kwaadwillende webpagina gebruikers misleidt om een verzoek uit te voeren dat niet bedoeld is, bijvoorbeeld door bookmarklets, iframes te gebruiken of gewoon door een pagina te maken die visueel genoeg op elkaar lijkt om gebruikers voor de gek te houden.

De Rails CSRF-beschermingis gemaakt voor ” klassieke” web-apps – het geeft gewoon een zekere mate van zekerheid dat het verzoek afkomstig is van uw eigen web-app. Een CSRF-token werkt als een geheim dat alleen uw server kent – Rails genereert een willekeurig token en slaat het op in de sessie. Uw formulieren verzenden het token via een verborgen invoer en Rails verifieert dat elk niet-GET-verzoek een token bevat dat overeenkomt met wat is opgeslagen in de sessie.

Een API is echter meestal per definitie cross-site en bedoeld om in meer dan alleen uw web-app te worden gebruikt, wat betekent dat het hele concept van CSRF niet helemaal van toepassing is.

In plaats daarvan moet u een op tokens gebaseerde strategie gebruiken voor het verifiëren van API-verzoeken met een API-sleutel en geheim, aangezien u verifieert dat het verzoek afkomstig is van een goedgekeurde API-client en niet van uw eigen app.

Je kunt CSRF deactiveren zoals aangegeven door @dcestari:

class ApiController < ActionController::Base
  protect_from_forgery with: :null_session
end

Bijgewerkt.In Rails 5 kun je API-only applicaties genereren door de --apioptie te gebruiken:

rails new appname --api

Ze bevatten niet de CSRF-middleware en vele andere componenten die overbodig zijn.


Antwoord 2, autoriteit 74%

Een andere manier om CSRF uit te schakelen die geen null-sessie weergeeft, is door het volgende toe te voegen:

skip_before_action :verify_authenticity_token

in uw Rails-controller. Dit zorgt ervoor dat je nog steeds toegang hebt tot sessie-informatie.

Nogmaals, zorg ervoor dat u dit alleen doet in API-controllers of op andere plaatsen waar CSRF-beveiliging niet helemaal van toepassing is.


Antwoord 3, autoriteit 17%

Er is relevante informatie over een configuratie van CSRF met betrekking tot API-controllers op api.rubyonrails .org:

Het is belangrijk om te onthouden dat XML- of JSON-verzoeken ook worden beïnvloed en als u een APIu moet de beschermingsmethode tegen vervalsing wijzigen in ApplicationController(standaard: :exception):

class ApplicationController < ActionController::Base
  protect_from_forgery unless: -> { request.format.json? }
end

Misschien willen we CSRF-beveiliging voor API’s uitschakelen, omdat ze doorgaans zijn ontworpen om statusloos te zijn. Dat wil zeggen, de API-client voor het verzoek zal de sessie voor u afhandelen in plaats van Rails.


Antwoord 4, autoriteit 12%

Sinds de rails 5 kunt u ook een nieuwe klasse maken met :: api In plaats van :: base:

class ApiController < ActionController::API
end

5, Autoriteit 2%

Als u de monsteractie van de monstercontroller

wilt uitsluiten

class TestController < ApplicationController
  protect_from_forgery except: :sample
  def sample
   render json: @hogehoge
  end
end

U kunt zonder problemen verzoeken van buitenaf verwerken.


6

Als u alleen CSRF-bescherming wilt overslaan voor een of meer controlleracties (in plaats van de volledige controller), probeer dit dan

skip_before_action :verify_authenticity_token, only [:webhook, :index, :create]

Waar [:webhook, :index, :create]Sla de cheque over voor die 3 acties, maar u kunt veranderen in welke u

wilt overslaan


7

De eenvoudigste oplossing voor het probleem is om standaard dingen in je controller te doen of je kunt het direct in ApplicationControllerzetten:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception, prepend: true
end

Other episodes