使用浅路径保护rails API

时间:2014-05-15 19:36:55

标签: ruby-on-rails ruby ruby-on-rails-4

我正在构建一个JSON api,它将成为另一个rails站点的数据源(使用devise for auth),并且具有基本令牌认证功能。 API还将负责向移动应用程序提供数据。

在API中,我有以下模型: 用户,书籍和章节 用户has_many:书籍,书籍has_many:章节。在我的路线文件中,我有

shallow do
  resources :users do
    resources :books do
      resources :chapters
    end
  end
end

这会产生如下路线:

/users/:user_id , /users/:user_id/books
/books/:book_id , /books/:book_id/chapters
/chapters/:chapter_id 

ie'浅路线'而不是/ users /:user_id / books /:book_id / chapters /:chapter_id

我想知道我应该如何对这些进行身份验证,因为这一章并不属于用户。这不仅仅是检查user_id的情况(因为这是书籍模型的一个属性) )。

# chapters_controller
def show
  @chapter = Chapter.find(params[:id])
end

我是否必须获取@ chapter的书,然后检查其user_id? 某种程度上对我来说并不合适。我是朝着错误的方向前进的吗?

感谢阅读!

1 个答案:

答案 0 :(得分:1)

我发现一种技术可以让控制器建立一个模型范围,限制当前经过身份验证的用户可见/可更新/可销毁的内容。

我首先使用request_store gem在我的User模型上从我的控制器设置当前用户和请求信息,这只是一个小的垫片,比线程本地存储有点清理。

这可以通过User课程从我的任何模型中获取用户和请求信息。我可以在任何需要的地方使用User.currentUser.requestUser.location

您的控制器只需在对用户进行身份验证后设置User.currentUser.request即可。这在构建模型中的范围时非常有用,因为它们可以限制当前用户可以访问的范围。

您可以在模型上定义范围,例如visible,可以在相关模型上执行where(:owner => User.current.id)或类似操作,以限制当前模型的可见/可更新/可销毁的内容。

然后您的控制器只需调用SomeModel.visibleSomeModel.updateableSomeModel.destroyable,它将获得一个限制为可读/写/销毁的范围。基于该模型范围的任何find只有在模型确实在用户的范围规则范围内时才会成功!

示例用户模型:

# models/user.rb
require 'request_store'

class User

  def self.current
    RequestStore.store[:current_user]
  end

  def self.current=(user)
    RequestStore.store[:current_user] = user
  end

  def self.request
    RequestStore.store[:current_request]
  end

  def self.request=(request)
    # stash the request so things like IP address and GEO-IP based location is available to other models
    RequestStore.store[:current_request] = request
  end

  def self.location
    # resolve the location just once per request
    RequestStore.store[:current_location] ||= self.request.try(:location)
  end
end