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

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

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

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

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

如果您正在使用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 )。 您可能可以使用此代码实现相同的function(完全未经测试):

 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