如何为Graphene Relay的Node和Connection字段设置认证授权权限
针对你用Graphene-Django定义的tier节点字段和all_tiers连接字段,有3种常用的认证/授权校验配置方案,按需选择即可:
方案1:字段级装饰器(灵活度最高,适合单字段自定义规则)
给每个查询字段单独编写resolve方法,用装饰器加校验规则,不同字段可以配置完全不同的权限逻辑:
from graphene_django.decorators import login_required from graphql import GraphQLError # 自定义权限校验装饰器示例,比如校验是否为管理员 def admin_permission_required(func): def wrapper(root, info, **kwargs): if not info.context.user.is_staff: raise GraphQLError("您没有权限访问该资源") return func(root, info, **kwargs) return wrapper class Query(graphene.ObjectType): tier = relay.Node.Field(TierNode) all_tiers = DjangoFilterConnectionField(TierNode) # tier字段校验规则:登录 + 管理员权限 @login_required @admin_permission_required def resolve_tier(self, info, **kwargs): return relay.Node.Field.get_node(TierNode, info, kwargs.get('id')) # all_tiers字段校验规则:仅需登录 @login_required def resolve_all_tiers(self, info, **kwargs): # 这里也可以加行级权限过滤,比如只返回当前用户关联的Tier数据 # return Tier.objects.filter(owner=info.context.user) return Tier.objects.all()
方案2:自定义带权限的字段类(适合批量复用规则)
如果多个模型的查询都要走统一的权限规则,直接自定义字段类,不用每个字段重复写resolve方法:
from graphene_django.filter import DjangoFilterConnectionField from graphql import GraphQLError # 自定义带登录校验的Node节点字段 class AuthNodeField(relay.Node.Field): def get_resolver(self, parent_resolver): original_resolver = super().get_resolver(parent_resolver) def wrapper(root, info, **kwargs): # 登录校验 if not info.context.user.is_authenticated: raise GraphQLError("请先登录后再访问") # 额外权限校验可在这里扩展 return original_resolver(root, info, **kwargs) return wrapper # 自定义带登录校验的Connection连接字段 class AuthFilterConnectionField(DjangoFilterConnectionField): @classmethod def resolve_queryset(cls, connection, iterable, info, args, filtering_args, filterset_class): qs = super().resolve_queryset(connection, iterable, info, args, filtering_args, filterset_class) if not info.context.user.is_authenticated: raise GraphQLError("请先登录后再访问") # 可扩展全局过滤逻辑,比如软删除数据过滤、行权限过滤 return qs.filter(is_delete=False) # 直接替换原有字段类型即可自动生效权限规则 class Query(graphene.ObjectType): tier = AuthNodeField(TierNode) all_tiers = AuthFilterConnectionField(TierNode)
方案3:DjangoObjectType层面全局配置(适合单模型所有查询共用规则)
如果所有和TierNode相关的查询都要走相同的权限规则,直接重写TierNode的get_node方法即可,所有关联查询自动生效:
class TierNode(DjangoObjectType): class Meta: model = Tier filter_fields = [] interfaces = (graphene.relay.Node,) @classmethod def get_node(cls, info, id): # 统一加权限校验 if not info.context.user.is_authenticated: raise GraphQLError("请先登录") if not info.context.user.has_perm('your_app_name.view_tier'): raise GraphQLError("您没有查看Tier数据的权限") return super().get_node(info, id)
注意事项
- 所有校验逻辑都可以从
info.context.user直接拿到当前请求的登录用户,这是Graphene-Django默认从Django请求上下文注入的 - 权限不足时抛出
GraphQLError即可,前端会收到对应的错误提示 - 如果你用JWT等第三方认证方式,要确保对应的中间件已经正确配置,
info.context.user才能拿到正确的用户信息
内容的提问来源于stack exchange,提问作者atm
相关产品推荐
相关产品推荐

