GraphQL(六)登录态校验Directive
GraphQL Directive(指令)是GraphQL中的一种特殊类型,它允许开发者在GraphQL schema中添加元数据,以控制查询和解析操作的行为
Directive的详细说明及使用可见GraphQL(五)指令[Directive]详解
本文将介绍通过自定义Directive实现的GraphQL登录态校验,步骤依次为:
Schema中定义directive- 实现
DgsReactiveCustomContextBuilderWithRequest接口,构建请求内全局使用的上下文对象 - 实现
SchemaDirectiveWiring,对Field进行拦截校验 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);}}
}
参考资料:
- GraphQL(五)指令[Directive]详解
- Derectives 原理
相关文章:
GraphQL(六)登录态校验Directive
GraphQL Directive(指令)是GraphQL中的一种特殊类型,它允许开发者在GraphQL schema中添加元数据,以控制查询和解析操作的行为 Directive的详细说明及使用可见GraphQL(五)指令[Directive]详解 本文将介绍通过…...
强大的AI语言模型
1.kameAI 点我 1️⃣可以绘图 2️⃣对接4.0 3️⃣具有长篇写作...
成集云 | 鼎捷ERP采购单同步钉钉 | 解决方案
源系统成集云目标系统 方案介绍 鼎捷ERP(Enterprise Resource Planning)是一款综合性的企业管理软件,它包括了多个模块来管理企业的各个方面,其中之一就是采购订单模块。鼎捷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的读写请求量很大,那么单个实例很有可能承担不了这么大的请求量,如何提高Redis的性能呢?你也许已经想到了,可以部署多个副本节点,业务采用…...
Python爬虫:如何使用Python爬取网站数据
更新:2023-08-13 15:30 想要获取网站的数据?使用Python爬虫是一个绝佳的选择。Python爬虫是通过自动化程序来提取互联网上的信息。本文章将会详细介绍Python爬虫的相关技术。 一、网络协议和请求 在使用Python爬虫之前,我们需要理解网络协…...
剑指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中用于构建神经网络模型的核心模块。它提供了各种类和函数,可以帮助你定义和训练神经网络。class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__() #调用 super(Tudui,…...
kafka使用心得(二)
kafka进阶 消息顺序保证 Kafka它在设计的时候就是要保证分区下消息的顺序,也就是说消息在一个分区中的顺序是怎样的,那么消费者在消费的时候看到的就是什么样的顺序。 消费者和分区的对应关系 参考这篇文章。 分区文件 一个分区对应着log.dirs下的…...
(二)掌握最基本的Linux服务器用法——Linux下简单的C/C++ 程序、项目编译
1、静态库与动态库 静态库(Static Library):静态库是编译后的库文件,其中的代码在编译时被链接到程序中,因此它会与程序一起形成一个独立的可执行文件。每个使用静态库的程序都会有自己的库的副本,这可能会导致内存浪费。常用后缀…...
应急响应-钓鱼邮件的处理思路溯源及其反制
0x00 钓鱼邮件的危害 1.窃取用户敏感信息,制作虚假网址,诱导用户输入敏感的账户信息后记录 2.携带病毒木马程序,诱导安装,使电脑中病毒木马等 3.挖矿病毒的传输,勒索病毒的传输等等 0x01 有指纹的钓鱼邮件的溯源处理…...
Hadoop Hbase Hive 版本对照一览
这里写目录标题 一、Hadoop 与 Hbase 版本对照二、Hadoop 与 Hive 版本对照 官网内容记录,仅供参考 一、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中用于进行调试和输出日志的类。它提供了一种便捷的方式来输出各种类型的数据,并可轻松地与流式输出一起使用,方便调试和查看程序的运行情况。 引入QDebug: 在使用QDebug…...
【C++】面试题
1、都说c是面向对象的语言,面向对象的三个特性能 [展开] 介绍一下吗? 封装:封装是一种集中管理的思想,把内部的数据和实现方法组合在一起,并且不对外暴漏内部的数据和实现方法,只对外提供几个接口来完成函数…...
机器学习算法之-逻辑回归(1)
什么是回归 回归树,随机森林的回归,无一例外他们都是区别于分类算法们,用来处理和预测连续型标签的算法。然而逻辑回归,是一种名为“回归”的线性分类器,其本质是由线性回归变化而来的,一种广泛使用于分类问…...
JAVA多线程和并发基础面试问答(翻译)
JAVA多线程和并发基础面试问答(翻译) java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序…...
正中优配:2023新股上市涨跌幅规则?新股上市涨跌幅限制为几天?
A股与美股不同,股票存在涨跌幅限制,那么,2023新股上市涨跌幅规矩?新股上市涨跌幅限制为几天?下面正中优配为我们预备了相关内容,以供参阅。 2023年新股上市涨跌幅存在以下规矩: 1、主板初次公开…...
如何查看线程在哪个cpu核上
1、ps -eLF查看PSR值 2、 taskset -pc $pid(进程/线程) 参考链接:https://blog.csdn.net/test1280/article/details/87993669...
【Vue前端】设置标题用于SEO优化
原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 1.vue全局配置2.创建并暴露getPageTitle方法3.通过全局前置守卫设置title4.页面上引用title5.项目使用中英文翻译,title失效 1.vu…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
