You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:36:03