使用Devise设置API进行身份验证

时间:2017-02-22 05:15:23

标签: ruby-on-rails api devise user-registration

我正在尝试为我的rails应用程序设置用户注册端点,以便我可以在iOS再现中访问应用程序功能。我已经开始使用命名空间我的API,到目前为止已经设法使用Devise和JWT进行用户身份验证。

这很棒,但我还需要能够通过API注册用户。坦率地说,我不知道如何正确实现这一点。多个GOogle版本会显示outdated articles,使用deprecated token authenticatable,或者从未接听过。

以下是我认为最符合此问题的代码:

routes.rb(API的Namespaced部分)

override func viewDidLoad()

    {

        super.viewDidLoad()

        FIRDatabase.database().reference(withPath: "Main data").child("Home Image URLs").observeSingleEvent(of: .value, with: { (snapshot) in

            if let snapString = snapshot.value as? String {



           self.imageURLsVAR = snapString

                self.imageURLs = self.imageURLsVAR.components(separatedBy: ",")

      //     self.label.text = String(self.imageURLs[1])

          for i in 0..< imageURLs.count-1{
          let imageview = UIImageView()
       // imageview.image = homeImages[i]
          dlURL = String(imageURLs[i])


          DLImageLoader.sharedInstance().image(fromUrl: String(imageURLs[i]), imageView: imageview)
            imageview.contentMode = .scaleAspectFit
            let xPosition = self.view.frame.width * CGFloat(i)
            imageview.frame = CGRect(x: xPosition, y: 0, width: self.imgScrollView.frame.width, height: self.imgScrollView.frame.height)
            imgScrollView.contentSize.width = imgScrollView.frame.width * CGFloat(i + 1)
            imgScrollView.addSubview(imageview)
            view.sendSubview(toBack: imgScrollView)
        }
            }

    }) { (error) in
        print(error.localizedDescription)
    }


}

registrations_controller.rb(API contorller)

namespace :api do
   namespace :v1 do
      devise_for :users, controllers: { registrations: 'api/v1/registrations' }
         resources :classrooms
         resources :notifications
      end
   end
end

注册终点

class Api::V1::RegistrationsController < Devise::RegistrationsController respond_to :json def create if params[:email].nil? render :status => 400, :json => {:message => 'User request must contain the user email.'} return elsif params[:password].nil? render :status => 400, :json => {:message => 'User request must contain the user password.'} return end if params[:email] duplicate_user = User.find_by_email(params[:email]) unless duplicate_user.nil? render :status => 409, :json => {:message => 'Duplicate email. A user already exists with that email address.'} return end end @user = User.create(user_params) if @user.save! render :json => {:user => @user} else render :status => 400, :json => {:message => @user.errors.full_messages} end end private # Never trust parameters from the scary internet, only allow the white list through. def user_params devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute, :first_name, :last_name, :access_code]) end end

邮递员样本回复

http://localhost:3000/api/v1/users

我非常感谢任何帮助,因为我渴望学习更多(并让它发挥作用!)。

更新1

这是我在发出生成用户的帖子请求后在服务器上得到的内容......

{
  "message": [
    "Email can't be blank",
    "Password can't be blank",
    "Access code is invalid [Beta]."
  ]
}

更新了Registrations_controller

Started POST "/api/v1/users" for 127.0.0.1 at 2017-02-22 09:22:11 -0800
Processing by Api::V1::RegistrationsController#create as */*
  Parameters: {"user"=>{"email"=>"user@sampleapi.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "access_code"=>"uiux"}}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."email" IS NULL LIMIT $1  [["LIMIT", 1]]
Completed 400 Bad Request in 2ms (Views: 0.2ms | ActiveRecord: 0.4ms)

我很确定我此时的主要问题是我的参数的格式,因此任何正确方向的推动都会很棒。我确实找到了this post,但我觉得它有点难以理解它们的API工作原理......

2 个答案:

答案 0 :(得分:4)

这是2个解决方案,选择你喜欢的解决方案。

  1. 覆盖devise_parameter_sanitizer:

    DbDataReader
  2. 覆盖sign_up_params:

    class ApplicationController < ActionController::Base
      protected
    
      def devise_parameter_sanitizer
        if resource_class == User
          User::ParameterSanitizer.new(User, :user, params)
        else
          super # Use the default one
        end
      end
    end
    
  3. 为什么?

    如果您深入Devise ParameterSanitizer,则由于您的路线,resource_name将为def sign_up_params params.require(:user).permit(:email, :password, :password_confirmation) end ,而不仅仅是:api_v1_user

    :user

    错误resource_name将导致namespace :api do namespace :v1 do devise_for :users, controllers: { registrations: 'api/v1/registrations' } end end 始终返回空哈希sign_up_params

答案 1 :(得分:0)

你为什么不尝试这样的事情:

user = User.create(sign_up_params)
if user.save
  render status: 200, json: @controller_blablabla.to_json
else
  render :status => 400,
         :json => {:message => @user.errors.full_messages}
end

甚至更好。您可以使用tiddle gem之类的东西来提高会话的安全性:

respond_to :json
def create
 user = User.create(sign_up_params)
 if user.save
   token = Tiddle.create_and_return_token(user, request)
   render json: user.as_json(authentication_token: token, email: 
                user.email), status: :created
   return
 else
   warden.custom_failure!
   render json: user.errors, status: :unprocessable_entity
 end
end

您可以使用httpie --form发出请求:

http --form POST :3000/users/sign_up Accept:'application/vnd.sign_up.v1+json' user[email]='he@llo.com' user[username]='hello' user[password]='123456789' user[password_confirmation]='123456789'

不要忘记:

def sign_up_params
  params.require(:user).permit(:username, :email, :password, :password_confirmation)
end

我不知道自己错过了什么,让我知道如果我错了或出了什么问题我都没有意识到!

问候!