使用devise进行RESTful登录(Rails 4) [英] RESTful login with devise (Rails 4)
问题描述
如何在Ruby on Rails中使用devise进行RESTful注册和登录(我正在使用第4版)?
How do I do RESTful sign-up and sign-in using devise in Ruby on Rails (I am using version 4)?
我找不到任何文档关于我应该POST到服务器的参数(例如电子邮件,密码)。
I could not find any documentation with regards to the parameters (e.g. email, password) that I should POST to the server.
似乎不支持使用JSON数据(例如通过AJAX)的RESTful登录在当前版本的设计中开箱即用 - 默认行为是发送任何类型请求的整个HTML页面,而不是专门处理JSON请求的JSON对象。
It seems that RESTful login using JSON data (e.g. via AJAX) is not supported out of the box in the current version of devise - the default behavior is to send back a whole HTML page for any type of request made, instead of a JSON object for handling JSON request specifically.
这是否意味着我需要创建/扩展自定义控制器来处理使用JSON的RESTful应用程序的用户注册和登录?如果是,请详细说明。
Does this mean that I need to create/extend custom controller for handling user registration and login for RESTful apps using JSON? If so, please elaborate.
推荐答案
如果您使用Devise,所有RESTful操作都是通过他们的表单和;控制器(如果您浏览到 http://your-app.com/users/sign_up
,您将能够注册等)
If you're using Devise, all of the RESTful actions have been provided through their forms & controller (if you browse to http://your-app.com/users/sign_up
, you'll be able to register etc)
如果你想让你的Devise处理JSON,你是正确的,因为它没有处理开箱即用,但幸运的是有一个办法:
If you're looking to make your Devise handle JSON, you are correct in that it's not handled "out of the box", but fortunately, there is a way to do it:
实时代码
#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 )。您可能可以使用此代码实现相同的功能(完全未经测试):
This is probably excessive, but it works (try registering or logging in at http://firststop.herokuapp.com). You could probably achieve the same thing with this code (completely untested):
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
这篇关于使用devise进行RESTful登录(Rails 4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!