总结一下GraphQL-Ruby的授权机制

首先

最近我有机会使用GraphQL-Ruby来实现授权功能,所以我想总结一下。
术语上有认证和授权两个概念,但这次我们只涉及授权。(通常情况下,GraphQL不涉及认证)

给resolver和mutation添加授权

首先,我们将总结可用于resolver和mutation授权的方法。您可以在以下链接找到更多信息:https://graphql-ruby.org/mutations/mutation_authorization.html

准备好了吗?

准备好了吗?可以在解析器(resolver)或变更(mutation)中使用ready?方法。ready?方法会在执行变更前自动调用。如果返回值为false,将返回null,但更好的做法是引发GraphQL错误,就像示例一样。

class Mutations::PromoteEmployee < Mutations::BaseMutation
  def ready?(**args) # argsはmutationの引数
    if !context[:current_user].admin?
      raise GraphQL::ExecutionError, "Only admins can run this mutation"
    else
      true
    end
  end

  def resolver(**args)
    # mutation実行
  end
end

授权了吗?

突变/mutation对象还提供了authorized?方法。实际上,这个方法与ready?方法几乎有相同的功能。将上述的ready?替换为authorized?,同样也能正常工作。唯一的区别在于是否加载arguments。

当加载arguments时,指的是当定义了argument并通过employee_id来获取在loads中定义的Employee对象时,它会自动从数据库中获取(可能是这个意思)。

argument :employee_id, ID, required: true, loads: Types::Employee

如果按照上述情况,将获取由参数指定的id的员工对象。因此,可以利用authorized?方法,写成以下形式。

argument :employee_id, ID, required: true, loads: Types::Employee

def authorized?(employee:)
  context[:current_user].manager_of?(employee)
end

给予对象类型授权

在GraphQL-Ruby中,具有关联的对象可以在客户端自由获取。这可能导致访问本应需要权限的资源,为了防止这种情况发生,可以通过为每个对象类型设置授权来进行总结。

使用”visible”吗?

https://graphql-ruby.org/authorization/visibility.html
visible?方法的作用是使模式本身对用户不可见。例如,可以考虑将实验性功能仅开放给特定用户的用例。
在下面的示例中,如果visible?方法的返回值为false,则将返回GraphQL错误。

  class secretType < BaseObject
    def self.visible?(context)
     context[:current_user].admin?
    end

    field :hoge, Hoge, null: true
  end

用得了 authorized 吗?

https://graphql-ruby.org/authorization/authorization.html
在这里,这个authorized?方法看起来像是用来进行授权的。从名字上来看,确实是这样的。
在下面的例子中,如果current_user等于object.user,那么会返回Object,如果不相等,则返回null。

  class secretType < BaseObject
    def self.authorized?(object, context)
     context[:current_user] === object.user
    end

    field :hoge, Hoge, null: true
  end

另外,如果想在authorized方法返回false时返回错误,可以在模式的顶层定义错误。

class MySchema < GraphQL::Schema
  def self.unauthorized_object(error)
    raise GraphQL::ExecutionError, "An object of type #{error.type.graphql_name} was hidden due to permissions"
  end
end

使用范围

使用 `authorized?` 方法后,我们可以选择返回或不返回对象。但是,有时我们可能希望限制返回对象的用户范围。这种情况下,`scope` 方法非常有用。
在以下示例中,如果用户是管理员,则返回所有对象;否则,返回已发布的产品。

  class prodcutType < BaseObject
      def self.scope_items(items, context)
        context[:current_user].admin? items : items.published
      end
  end

您可以通过 field 参数来定义是否应用此 scope。

field :products, [Types::Product] scope: true

如果返回值是数组,则默认为true,如果是值,则为false。

总而言之

上述是对GraphQL-Ruby授权的总结。由于GraphQL的授权相当复杂,所以我们希望能够彻底整理一下!

广告
将在 10 秒后关闭
bannerAds