当前位置: 首页 > news >正文

GraphQL(六)登录态校验Directive

GraphQL Directive(指令)是GraphQL中的一种特殊类型,它允许开发者在GraphQL schema中添加元数据,以控制查询和解析操作的行为

Directive的详细说明及使用可见GraphQL(五)指令[Directive]详解

本文将介绍通过自定义Directive实现的GraphQL登录态校验,步骤依次为:

  1. Schema中定义directive
  2. 实现DgsReactiveCustomContextBuilderWithRequest接口,构建请求内全局使用的上下文对象
  3. 实现SchemaDirectiveWiring,对Field进行拦截校验
  4. Directive注入

Schema Directive定义

"必须要登录"
directive @needLogin on FIELD_DEFINITIONtype Employee {"雇员名称"employees(month: Date : [String] @needLogin
}

LoginContextBuilder

实现DgsReactiveCustomContextBuilderWithRequest接口,可以使用当前的请求信息,例如 HTTP 请求头、请求参数等构建自定义的上下文对象

在查询执行过程中,GraphQL 会将该上下文对象传递给所有的数据解析器(DataFetcher),使得数据解析器能够访问和修改上下文对象中的数据

使用DgsReactiveCustomContextBuilderWithRequest接口可以实现许多有用的功能,例如:

  • 存储用户身份验证信息,以便在数据解析器中进行鉴权
  • 将请求相关的信息(例如请求参数、请求头等)传递给数据解析器,以便数据解析器根据这些信息返回正确的数据
  • 存储请求相关的上下文信息,例如请求开始时间、请求结束时间等,以便进行性能分析和监控
@Component
public class LoginContextBuilder implements DgsReactiveCustomContextBuilderWithRequest<YyContext> {private static final Logger LOGGER = LoggerFactory.getLogger(LoginContextBuilder.class);@Autowiredprivate ReactiveLoginService reactiveLoginService;@Autowiredprivate HttpHeaderAuthorization httpHeaderAuthorization;@NotNull@Overridepublic Mono<LoginContext> build(@Nullable Map<String, ?> map, @Nullable HttpHeaders httpHeaders, @Nullable ServerRequest serverRequest) {boolean interiorAuth = httpHeaderAuthorization.auth(serverRequest);if(interiorAuth){LoginContext loginContext = new LoginContext(true, IpUtil.getClientIpAddress(serverRequest)).setInteriorAuth(true);LOGGER.info("interior request loginContext:{}",loginContext);return Mono.just(loginContext);}else{return reactiveLoginService.getUid(serverRequest).doOnSuccess(user-> LOGGER.info("login user:{}",user)).onErrorResume(e-> Mono.just(LoginUser.NOT_LOGIN_USER)).map(user -> new LoginContext(user, IpUtil.getClientIpAddress(serverRequest)));}}
}

ReactiveLoginService

subscribeOn(Schedulers.boundedElastic())将该Mono订阅到一个boundedElastic调度器的线程中,这样Mono中的操作就会在该线程上执行,而不会阻塞当前的线程

Schedulers.boundedElastic()调度器是一个弹性线程池,它根据需要动态地创建和销毁线程,以适应不同的负载情况

public class ReactiveLoginService {private LoginService loginService;public ReactiveLoginService(LoginService loginService){this.loginService = loginService;}/*** 登录校验* @param httpServerRequest* @return*/public Mono<LoginUser> getUid(ServerRequest httpServerRequest){return Mono.fromCallable(()->{long uid = loginService.login(new WebFluxHttpServletRequest(httpServerRequest),null);return uid > 0 ? new LoginUser(uid) : LoginUser.NOT_LOGIN_USER;}).subscribeOn(Schedulers.boundedElastic());}public void close(){loginService.close();}
}

Directive 实现

@Component
public class NeedLoginDirective implements SchemaDirectiveWiring {private static final Logger LOGGER = LoggerFactory.getLogger(NeedLoginDirective.class);public static final String NEED_LOGIN_DIRECTIVE = "needLogin";public NeedLoginDirective() {}@Overridepublic GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> environment) {GraphQLFieldDefinition field = environment.getElement();GraphQLFieldsContainer parentType = environment.getFieldsContainer();// 原始DataFetcher,无需修改参数值时,最后需返回原始DataFetcher的值DataFetcher originalDataFetcher = environment.getCodeRegistry().getDataFetcher(parentType, field);if (field.getDirective(NEED_LOGIN_DIRECTIVE) == null) {return field;}LOGGER.info("onField field:{} needLogin.", field);DataFetcher needLoginDataFetcher = dfe -> {LoginContext loginContext = DgsContext.getCustomContext(dfe);if (loginContext.getLoginUser().hasLogin()) {return originalDataFetcher.get(dfe);} else {LOGGER.info("not login return null");throw new NeedLoginRuntimeException();}};environment.getCodeRegistry().dataFetcher(parentType, field, needLoginDataFetcher);return field;}
}

Directive 注入

GraphQLSchemaConfiguration

@Configuration
public class GraphQLSchemaConfiguration {@DgsComponentpublic class SecuredDirectiveRegistration {private NeedLoginDirective needLoginDirective;public SecuredDirectiveRegistration(NeedLoginDirective needLoginDirective) {this.needLoginDirective = needLoginDirective;}@DgsRuntimeWiringpublic RuntimeWiring.Builder addSecuredDirective(RuntimeWiring.Builder builder) {return builder.directive(NeedLoginDirective.NEED_LOGIN_DIRECTIVE,needLoginDirective);}}
}

参考资料:

  1. GraphQL(五)指令[Directive]详解
  2. Derectives 原理

相关文章:

GraphQL(六)登录态校验Directive

GraphQL Directive&#xff08;指令&#xff09;是GraphQL中的一种特殊类型&#xff0c;它允许开发者在GraphQL schema中添加元数据&#xff0c;以控制查询和解析操作的行为 Directive的详细说明及使用可见GraphQL&#xff08;五&#xff09;指令[Directive]详解 本文将介绍通过…...

强大的AI语言模型

1.kameAI 点我 1️⃣可以绘图 2️⃣对接4.0 3️⃣具有长篇写作...

成集云 | 鼎捷ERP采购单同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 鼎捷ERP&#xff08;Enterprise Resource Planning&#xff09;是一款综合性的企业管理软件&#xff0c;它包括了多个模块来管理企业的各个方面&#xff0c;其中之一就是采购订单模块。鼎捷ERP的采购订单模块可以帮助企业有效管理和控制采购过程…...

【Kubernetes】Kubernetes的PV和PVC的用法

PV、PVC 前言一、 存储卷1. emptyDir 存储卷1.1 概念1.2 实例 2. hostPath 存储卷2.1 概念2.2 实例 3. nfs共享存储卷 二、PV 和 PVC1. 概念1.1 PV1.2 PVC1.3 PVC 的使用逻辑1.4 创建机制1.5 PV 和 PVC 的生命力周期1.6 创建及销毁 PV 的流程 2. PV 和 PVC 的创建2.1 查看定义2…...

【Redis】Redis三种集群模式-主从、哨兵、集群各自架构的优点和缺点对比

文章目录 前言1. 单机模式2. 主从架构3. 哨兵4. 集群模式总结 前言 如果Redis的读写请求量很大&#xff0c;那么单个实例很有可能承担不了这么大的请求量&#xff0c;如何提高Redis的性能呢&#xff1f;你也许已经想到了&#xff0c;可以部署多个副本节点&#xff0c;业务采用…...

Python爬虫:如何使用Python爬取网站数据

更新&#xff1a;2023-08-13 15:30 想要获取网站的数据&#xff1f;使用Python爬虫是一个绝佳的选择。Python爬虫是通过自动化程序来提取互联网上的信息。本文章将会详细介绍Python爬虫的相关技术。 一、网络协议和请求 在使用Python爬虫之前&#xff0c;我们需要理解网络协…...

剑指offer专题2:队列和栈

用两个栈模拟队列 class CQueue {stack<int> stack1;stack<int> stack2; public:CQueue() {}void appendTail(int value) {stack1.push(value);}int deleteHead() {int val-1;if(!stack2.empty()){val stack2.top();stack2.pop();}else if(!stack1.empty()){while…...

pytorch入门-神经网络

神经网络的基本骨架 import torch from torch import nn #nn模块是PyTorch中用于构建神经网络模型的核心模块。它提供了各种类和函数&#xff0c;可以帮助你定义和训练神经网络。class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__() #调用 super(Tudui,…...

kafka使用心得(二)

kafka进阶 消息顺序保证 Kafka它在设计的时候就是要保证分区下消息的顺序&#xff0c;也就是说消息在一个分区中的顺序是怎样的&#xff0c;那么消费者在消费的时候看到的就是什么样的顺序。 消费者和分区的对应关系 参考这篇文章。 分区文件 一个分区对应着log.dirs下的…...

(二)掌握最基本的Linux服务器用法——Linux下简单的C/C++ 程序、项目编译

1、静态库与动态库 静态库(Static Library)&#xff1a;静态库是编译后的库文件&#xff0c;其中的代码在编译时被链接到程序中&#xff0c;因此它会与程序一起形成一个独立的可执行文件。每个使用静态库的程序都会有自己的库的副本&#xff0c;这可能会导致内存浪费。常用后缀…...

应急响应-钓鱼邮件的处理思路溯源及其反制

0x00 钓鱼邮件的危害 1.窃取用户敏感信息&#xff0c;制作虚假网址&#xff0c;诱导用户输入敏感的账户信息后记录 2.携带病毒木马程序&#xff0c;诱导安装&#xff0c;使电脑中病毒木马等 3.挖矿病毒的传输&#xff0c;勒索病毒的传输等等 0x01 有指纹的钓鱼邮件的溯源处理…...

Hadoop Hbase Hive 版本对照一览

这里写目录标题 一、Hadoop 与 Hbase 版本对照二、Hadoop 与 Hive 版本对照 官网内容记录&#xff0c;仅供参考 一、Hadoop 与 Hbase 版本对照 二、Hadoop 与 Hive 版本对照...

Postgresql 基础使用语法

1.数据类型 1.数字类型 类型 长度 说明 范围 与其他db比较 Smallint 2字节 小范围整数类型 32768到32767 integer 4字节 整数类型 2147483648到2147483647 bigint 8字节 大范围整数类型 -9233203685477808到9223203685477807 decimal 可变 用户指定 精度小…...

Qt 之 QDebug,QString

文章目录 前言一、QDebug二、QString总结 前言 一、QDebug QDebug是Qt中用于进行调试和输出日志的类。它提供了一种便捷的方式来输出各种类型的数据&#xff0c;并可轻松地与流式输出一起使用&#xff0c;方便调试和查看程序的运行情况。 引入QDebug&#xff1a; 在使用QDebug…...

【C++】面试题

1、都说c是面向对象的语言&#xff0c;面向对象的三个特性能 [展开] 介绍一下吗&#xff1f; 封装&#xff1a;封装是一种集中管理的思想&#xff0c;把内部的数据和实现方法组合在一起&#xff0c;并且不对外暴漏内部的数据和实现方法&#xff0c;只对外提供几个接口来完成函数…...

机器学习算法之-逻辑回归(1)

什么是回归 回归树&#xff0c;随机森林的回归&#xff0c;无一例外他们都是区别于分类算法们&#xff0c;用来处理和预测连续型标签的算法。然而逻辑回归&#xff0c;是一种名为“回归”的线性分类器&#xff0c;其本质是由线性回归变化而来的&#xff0c;一种广泛使用于分类问…...

JAVA多线程和并发基础面试问答(翻译)

JAVA多线程和并发基础面试问答(翻译) java多线程面试问题 1. 进程和线程之间有什么不同&#xff1f; 一个进程是一个独立(self contained)的运行环境&#xff0c;它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序…...

正中优配:2023新股上市涨跌幅规则?新股上市涨跌幅限制为几天?

A股与美股不同&#xff0c;股票存在涨跌幅限制&#xff0c;那么&#xff0c;2023新股上市涨跌幅规矩&#xff1f;新股上市涨跌幅限制为几天&#xff1f;下面正中优配为我们预备了相关内容&#xff0c;以供参阅。 2023年新股上市涨跌幅存在以下规矩&#xff1a; 1、主板初次公开…...

如何查看线程在哪个cpu核上

1、ps -eLF查看PSR值 2、 taskset -pc $pid&#xff08;进程/线程&#xff09; 参考链接&#xff1a;https://blog.csdn.net/test1280/article/details/87993669...

【Vue前端】设置标题用于SEO优化

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 1.vue全局配置2.创建并暴露getPageTitle方法3.通过全局前置守卫设置title4.页面上引用title5.项目使用中英文翻译&#xff0c;title失效 1.vu…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

6.9-QT模拟计算器

源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...