使用devise进行RESTful登录(Rails 4)

 小娟2502895183 发布于 2023-02-13 15:09

如何在Ruby on Rails中使用设计进行RESTful注册和登录(我使用的是版本4)?

我找不到任何关于我应该POST到服务器的参数(例如电子邮件,密码)的文档.

在当前版本的设计中,似乎不支持使用JSON数据(例如通过AJAX)的RESTful登录 - 默认行为是为任何类型的请求发送回整个HTML页面,而不是JSON对象用于专门处理JSON请求.

这是否意味着我需要创建/扩展自定义控制器以使用JSON处理用户注册和登录RESTful应用程序?如果是这样,请详细说明.

1 个回答
  • 如果您正在使用Devise,则所有RESTful操作都是通过其表单和控制器提供的(如果您浏览http://your-app.com/users/sign_up,则可以注册等)

    如果你想让你的Devise处理JSON,你是正确的,因为它没有"开箱即用"处理,但幸运的是,有一种方法可以做到:

    现场代码

    #config/routes (notice custom controllers)
    devise_for :users, :path => '', :controllers => {:sessions => 'sessions', :registrations => 'registrations'}
    
    #app/controllers/registrations_controller.rb
    class RegistrationsController < DeviseController
      prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
      prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
    
      before_filter :configure_permitted_parameters
    
      prepend_view_path 'app/views/devise'
    
      # GET /resource/sign_up
      def new
        build_resource({})
        respond_with self.resource
      end
    
      # POST /resource
      def create
        build_resource(sign_up_params)
    
        if resource.save
          if resource.active_for_authentication?
            set_flash_message :notice, :signed_up if is_navigational_format?
            sign_up(resource_name, resource)
            respond_with resource, :location => after_sign_up_path_for(resource)
          else
            set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
            expire_session_data_after_sign_in!
            respond_with resource, :location => after_inactive_sign_up_path_for(resource)
          end
        else
          clean_up_passwords resource
    
          respond_to do |format|
            format.json { render :json => resource.errors, :status => :unprocessable_entity }
            format.html { respond_with resource }
          end
        end
      end
    
      # GET /resource/edit
      def edit
        render :edit
      end
    
      # PUT /resource
      # We need to use a copy of the resource because we don't want to change
      # the current user in place.
      def update
        self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
        prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
    
        if update_resource(resource, account_update_params)
          if is_navigational_format?
            flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
              :update_needs_confirmation : :updated
            set_flash_message :notice, flash_key
          end
          sign_in resource_name, resource, :bypass => true
          respond_with resource, :location => after_update_path_for(resource)
        else
          clean_up_passwords resource
          respond_with resource
        end
      end
    
      # DELETE /resource
      def destroy
        resource.destroy
        Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
        set_flash_message :notice, :destroyed if is_navigational_format?
        respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
      end
    
      # GET /resource/cancel
      # Forces the session data which is usually expired after sign
      # in to be expired now. This is useful if the user wants to
      # cancel oauth signing in/up in the middle of the process,
      # removing all OAuth session data.
      def cancel
        expire_session_data_after_sign_in!
        redirect_to new_registration_path(resource_name)
      end
    
      protected
    
      # Custom Fields
      def configure_permitted_parameters
        devise_parameter_sanitizer.for(:sign_up) do |u|
          u.permit(:first_name, :last_name,
            :email, :password, :password_confirmation)
        end
      end
    
      def update_needs_confirmation?(resource, previous)
        resource.respond_to?(:pending_reconfirmation?) &&
          resource.pending_reconfirmation? &&
          previous != resource.unconfirmed_email
      end
    
      # By default we want to require a password checks on update.
      # You can overwrite this method in your own RegistrationsController.
      def update_resource(resource, params)
        resource.update_with_password(params)
      end
    
      # Build a devise resource passing in the session. Useful to move
      # temporary session data to the newly created user.
      def build_resource(hash=nil)
        self.resource = resource_class.new_with_session(hash || {}, session)
      end
    
      # Signs in a user on sign up. You can overwrite this method in your own
      # RegistrationsController.
      def sign_up(resource_name, resource)
        sign_in(resource_name, resource)
      end
    
      # The path used after sign up. You need to overwrite this method
      # in your own RegistrationsController.
      def after_sign_up_path_for(resource)
        after_sign_in_path_for(resource)
      end
    
      # The path used after sign up for inactive accounts. You need to overwrite
      # this method in your own RegistrationsController.
      def after_inactive_sign_up_path_for(resource)
        respond_to?(:root_path) ? root_path : "/"
      end
    
      # The default url to be used after updating a resource. You need to overwrite
      # this method in your own RegistrationsController.
      def after_update_path_for(resource)
        signed_in_root_path(resource)
      end
    
      # Authenticates the current scope and gets the current resource from the session.
      def authenticate_scope!
        send(:"authenticate_#{resource_name}!", :force => true)
        self.resource = send(:"current_#{resource_name}")
      end
    
      def sign_up_params
        devise_parameter_sanitizer.sanitize(:sign_up)
      end
    
      def account_update_params
        devise_parameter_sanitizer.sanitize(:account_update)
      end
    end
    

    这可能过多,但它有效(尝试注册或登录http://firststop.herokuapp.com).您可以使用此代码实现相同的功能(完全未经测试):

    def create #-> completely untested & speculative
        super do |format|
            format.json { render :json => resource.errors, :status => :unprocessable_entity }
            format.html { respond_with resource }
        end
    end
    

    登录代码

    class SessionsController < DeviseController
      prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
      prepend_before_filter :allow_params_authentication!, :only => :create
      prepend_before_filter { request.env["devise.skip_timeout"] = true }
    
      prepend_view_path 'app/views/devise'
    
      # GET /resource/sign_in
      def new
        self.resource = resource_class.new(sign_in_params)
        clean_up_passwords(resource)
        respond_with(resource, serialize_options(resource))
      end
    
      # POST /resource/sign_in
      def create
        self.resource = warden.authenticate!(auth_options)
        set_flash_message(:notice, :signed_in) if is_navigational_format?
        sign_in(resource_name, resource)
    
            respond_to do |format|
                    format.json { render :json => {}, :status => :ok }
                    format.html { respond_with resource, :location => after_sign_in_path_for(resource) } 
            end
      end
    
      # DELETE /resource/sign_out
      def destroy
        redirect_path = after_sign_out_path_for(resource_name)
        signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
        set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
    
        # We actually need to hardcode this as Rails default responder doesn't
        # support returning empty response on GET request
        respond_to do |format|
          format.all { head :no_content }
          format.any(*navigational_formats) { redirect_to redirect_path }
        end
      end
    
    
      protected
    
      def sign_in_params
        devise_parameter_sanitizer.sanitize(:sign_in)
      end
    
      def serialize_options(resource)
        methods = resource_class.authentication_keys.dup
        methods = methods.keys if methods.is_a?(Hash)
        methods << :password if resource.respond_to?(:password)
        { :methods => methods, :only => [:password] }
      end
    
      def auth_options
        { :scope => resource_name, :recall => "#{controller_path}#new" }
      end
    end
    

    2023-02-13 15:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有