我正在尝试为iPhone应用程序构建rails API。 Devise适用于通过Web界面登录,但我需要能够使用REST API创建和销毁会话,我想使用JSON而不必在会话控制器上执行POST并且必须解析HTML并处理重定向。
我以为我可以这样做:
class Api::V1::SessionsController < Devise::SessionsController
def create
super
end
def destroy
super
end
end
并在config / routes.rb中添加:
namespace :api do
namespace :v1 do
resources :sessions, :only => [:create, :destroy]
end
end
rake路线显示路线设置正确:
api_v1_sessions POST /api/v1/sessions(.:format) {:action=>"create", :controller=>"api/v1/sessions"}
api_v1_session DELETE /api/v1/sessions/:id(.:format) {:action=>"destroy", :controller=>"api/v1/sessions"}
当我发布到/ user / sessions时,一切正常。我得到了一些HTML和302。
现在,如果我发布到/ api / v1 / sessions,我会得到:
未知行动 一个AbstractController :: ActionNotFound
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST http://localhost:3000/api/v1/sessions -d "{'user' : { 'login' : 'test', 'password' : 'foobar'}}"
答案 0 :(得分:40)
这是最终奏效的。
class Api::V1::SessionsController < Devise::SessionsController
def create
respond_to do |format|
format.html { super }
format.json {
warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
render :status => 200, :json => { :error => "Success" }
}
end
end
def destroy
super
end
end
同时更改routes.rb,记住顺序很重要。
devise_for :users, :controllers => { :sessions => "api/v1/sessions" }
devise_scope :user do
namespace :api do
namespace :v1 do
resources :sessions, :only => [:create, :destroy]
end
end
end
resources :users
答案 1 :(得分:10)
我最终结合了@ akshay的回答和@ mm2001的答案。
class Api::SessionsController < Devise::SessionsController
def create
warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
render :json => {:success => true}
end
def destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
render :json => {}
end
def failure
render :json => {:success => false, :errors => ["Login Failed"]}
end
end
...在设计初始化程序中,我必须这样做以使#create方法使用我的:recall
处理程序
# config/initializers/devise.rb
config.navigational_formats = [:"*/*", "*/*", :html, :json]
这是Devise 1.5.1和Rails 3.1。
答案 2 :(得分:8)
答案 3 :(得分:5)
我通过创建一个分配身份验证令牌的小服务解决了这个问题。我写了一篇关于它的博客文章:http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/。 您也可以在此处获取代码:https://github.com/matteomelani/Auth-Token-Service-Prototype。
答案 4 :(得分:1)
来自devise的#devise_scope的rdoc:
设置要在控制器中使用的设备范围。如果您有自定义路线, 您需要调用此方法(也别名为:as)才能指定 它被定位到哪个控制器。
as :user do
get "sign_in", :to => "devise/sessions#new"
end
请注意,您不能将两个范围映射到同一个URL。请记住,如果 你尝试访问设备控制器而不指定范围,它会 提出ActionNotFound错误。
看起来您需要将其包装在#as块中:
as :user do
namespace :api do
namespace :v1 do
resources :sessions, :only => [:create, :destroy]
end
end
end
答案 5 :(得分:1)
创建/销毁会话的另一种解决方案是使用Devise的token_authenticatable
模块,然后更新API中的其他功能,以便将令牌作为必需参数。这可以说是一个更具ReSTful的设计,因为它保留了无状态(即,任何地方都没有会话状态)。当然,这个建议适用于您的JSON API,但我不建议您的HTML UI使用相同的内容(浏览器的URL栏中的长令牌字符串不是很明显)。
有关示例,请参阅here。
答案 6 :(得分:0)