I am using devise
to sign up/in.
routes
get 'profile' => 'profile#get_profile'
post 'profile' => 'profile#create_profile'
and profile_controller
def get_profile
render json: {user: current_user}, status: :ok
end
def create_profile
render json: {user: current_user}, status: :ok
end
GET: http://localhost:3000/user/profile returns the expected output. However,
POST request throws an error saying:
ActionController::InvalidAuthenticityToken in User::ProfileController#create_profile
.
Please demystify this behavior.
To disable CSRF protection
you can edit your ApplicationController
like this:
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
# ...
end
or disable the CSRF protection
for specific controller:
class ProfilesController < ApplicationController
skip_before_action :verify_authenticity_token
# ...
end
:null_session
strategy empties the session instead of raising an exception which is perfect for an API . Because the session is empty, you can't use current_user
method or othes helpers that refer to the session
.
IMPORTANT :
protect_from_forgery with: :null_session
must be used only in specific cases, for example to allow API request (POST/PUT/PATCH/DELETE) without html form protect_from_forgery with: :null_session
you must restrict access to your data with an authorization system because every one could do request against your API endpoint protect_from_forgery with: :exception
for requests that are done through html form, is dangerous! (read here http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf ) To handle both standard requests (through html form) and API requests generally you have to set up two different controller for the same resource. Example:
Rails.application.routes.draw do
resources :profiles
namespace :api do
namespace :v1 do
resources :profiles
end
end
end
# app/controllers/application_controller.rb
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
(standard controller for html requests)
# app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
# POST yoursites.com/profiles
def create
end
end
(controller for API requests)
# app/controllers/api/v1/profiles_controller.rb
module Api
module V1
class ProfilesController < ApplicationController
# To allow only json request
protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
# POST yoursites.com/api/v1/profiles
def create
end
end
end
end
Get requests don't have an authenticity token.
You will have to add the request forgery stuff to your forms using this
<%= csrf_meta_tag %>
And address via javascript
$('meta[name="csrf-token"]')
In ApplicationController
(or another controller your controllers inherit from) there's a line:
protect_from_forgery with: :exception
Remove it and CSRF checks will be disabled.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.