簡體   English   中英

訪問Rails API devise中經過身份驗證的路由

[英]Access authenticated routes in rails api devise

有人可以幫我弄清楚如何通過Rails設計正確訪問經過身份驗證的路由嗎? 我已經弄清楚了如何對會話進行身份驗證並獲得令牌,但是當我在經過身份驗證的路由中傳遞該令牌時,遇到了需要登錄的錯誤。 這可能是卷曲的格式化問題,但是我是Rails的新手,我不太確定該怎么做。

我可以傳遞curl命令並獲取正確的令牌:

curl -X POST 'http://localhost:3000/users/sign_in.json' -d 'user[email]=user@name.com&user[password]=password'

我回來了:

{"token":"at6aig30jzulnnyomrm4c5","user_email":"user@name.com"}

問題是,當我嘗試訪問用戶的路由時,出現權限拒絕錯誤:

curl -L 'http://localhost:3000/users/me.json?token=at6aig30jzulnnyomrm4c5'
{"error":"You need to sign in or sign up before continuing."}

我有如下路線:

  devise_for :users, controllers: { sessions: 'sessions' }, :skip => [:passwords]
  resources :users, only: [:create, :update] do 
    get 'me' => 'users#me', on: :collection
  end

相應的路線如下所示:

      new_user_session GET        /users/sign_in(.:format)                  sessions#new
          user_session POST       /users/sign_in(.:format)                  sessions#create
  destroy_user_session DELETE     /users/sign_out(.:format)                 sessions#destroy
              me_users GET        /users/me(.:format)                       users#me
                 users POST       /users(.:format)                          users#create
                  user PATCH      /users/:id(.:format)                      users#update
                       PUT        /users/:id(.:format)                      users#update

我的用戶控制器如下所示:

class UsersController < ApplicationController
  before_action :authenticate_user!, except: [:create, :start_password_reset, :finish_password_reset]
  before_action :assert_reset_token_passed, only: [:finish_password_reset]

  def create
    user = User.new(register_params)

    if user.save
      render json: user, status: :created
    else
      render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def update
    if current_user.update(user_params)
      render json: current_user
    else
      render json: { errors: current_user.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def me
    if current_user
      render json: current_user, status: 200
    else
      render json: {}, status: 400
    end
  end

  def start_password_reset
    user = User.where(email: params[:email]).first
    user.send_reset_password_instructions if user
    render json: {}
  end

  def finish_password_reset
    user = User.with_reset_password_token(params[:reset_password_token])
    if user
      if user.reset_password!(reset_params[:password], reset_params[:password_confirmation])
        render json: {}
      else
        render json: { errors: user.errors.full_messages }, status: 400
      end
    else
      render json: { errors: ['Invalid password reset request.'] }, status: 403
    end
  end

  private

  def register_params
    params.require(:user).permit(:email, :password, :time_zone)
  end

  def user_params
    params.require(:user).permit(:include_email_memory, :time_zone, email_times: [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday])
  end

  def reset_params
    params.permit(:password, :password_confirmation)
  end

  # Check if a reset_password_token is provided in the request
  def assert_reset_token_passed
    render(json: { errors: ['Invalid password reset request.'] }, status: 403) if params[:reset_password_token].blank?
  end

end

對於它的價值,我正在嘗試使它與Ember simple-auth一起使用,以便可以正確加載用戶的個人資料。 謝謝您的幫助!

編輯:根據要求,這是我的應用程序控制器:

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
  skip_before_filter :verify_authenticity_token

  before_filter :authenticate_user_from_token!
  #before_filter :authenticate_user!

  around_action :user_time_zone, if: :current_user

  def index
    render file: 'public/index.html'
  end

  protected

  # def authenticate_user!
  #   render(json: {}, status: 401) unless current_user
  # end

  private

  def authenticate_user_from_token!
    authenticate_with_http_token do |token, options|
        user_email = options[:user_email].presence
        user       = user_email && User.find_by_email(user_email)

        if user && Devise.secure_compare(user.authentication_token, token)
          sign_in user, store: false
        end
      end
  end

  def user_time_zone(&block)
    Time.use_zone(current_user.time_zone, &block)
  end

  # If this is a get request for HTML, just render the ember app.
  def handle_html
    render 'public/index.html' if request.method == 'GET' && request.headers['Accept'].match(/html/)
  end
end

您只在請求中包含token

curl -L 'http://localhost:3000/users/me.json?token=at6aig30jzulnnyomrm4c5'

但您的服務器也希望該電子郵件也能通過:

authenticate_with_http_token do |token, options|
  user_email = options[:user_email].presence
  user       = user_email && User.find_by_email(user_email)
  …

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM