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

Idea+maven+spring-cloud项目搭建系列--11-2 dubbo鉴权日志记录数据统一封装

前言:使用dubbo做为通信组件,如果接口需要鉴权,和日志记录需要怎样处理;

1 鉴权:

1.1 在bootstrap.yml 中定义过滤器:
dubbo.provider.filter: 过滤器的名字:
在这里插入图片描述
1.2 resources 目录下创建配置文件:
1) resources 创建目录:/META-INF/dubbo
2) 创建文件名字为org.apache.dubbo.rpc.Filter 的纯文本文件:
在这里插入图片描述
3) 定义过滤器:
过滤器名字=过滤器路径地址
在这里插入图片描述
4)服务提供端:DubboTokenFilter:

package org.lgx.bluegrass.bluegrasses.dubbofilter;import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.filter.TokenFilter;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;
import org.lgx.bluegrass.bluegrasses.util.ApplicationContextUtils;
import org.lgx.bluegrass.bluegrasses.util.RedisUtil;
import org.springframework.util.StringUtils;/*** @Description TODO* @Date 2023/3/7 15:38* @Author lgx* @Version 1.0*/
public class DubboTokenFilter extends TokenFilter {private RedisUtil redisUtil;@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {String isNeedToken = invoker.getUrl().getParameter(Constants.TOKEN_KEY);// 是否需要进行token 验证if (StringUtils.hasText(isNeedToken)) {// 获取消费端传入的tokenString clientToken1 = invocation.getAttachment("dubbo_accesstoken");// 获取服务端的tokenString serverToken = getServerToken();//  token验证并且统一封装返回结果if (!serverToken.equals(clientToken1)) {// token 异常则直接封装ResponseDTO 并返回return AsyncRpcResult.newDefaultAsyncResult(ResponseDTO.defaultResponse("token illegal"), invocation);// 也可以抛出异常// Class<?> serviceType = invoker.getInterface();// throw new RpcException("Invalid token! Forbid invoke remote service " + serviceType + " method " + invocation.getMethodName() + "() from consumer " + RpcContext.getContext().getRemoteHost() + " to provider " + RpcContext.getContext().getLocalHost());}}return invoker.invoke(invocation);}// 从redis 中获取token 业务自行实现private String getServerToken() {if (null == redisUtil) {redisUtil = (RedisUtil) ApplicationContextUtils.getBean("redisUtil");}String accessToken = redisUtil.get("dubbo_accesstoken");return "1234";}
}

ResponseDTO 封装类:

// loomback 插件
@Data
@Accessors(chain = true)
public class ResponseDTO<T> implements Serializable {private static final long serialVersionUID = 3918877423924837166L;private int code = 200;private T body;private String msg;private boolean redirect = true;private List<ResponseMessage> messages;private List<String> message = new ArrayList<>();private int errNum;private String errorMsg;private Object errorObject;private boolean success = true;public static <T> ResponseDTO defaultResponse(T t) {return new ResponseDTO().setCode(BizHttpStatus.HTTP_STATUS_200.getStatus()).setBody(t);}
}

RedisUtil 封装类:stringRedisTemplate bean 自行配置实现

@Component
public class RedisUtil {@Autowired@Qualifier("stringRedisTemplate")private StringRedisTemplate redisTemplate;public void setRedisTemplate(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}public StringRedisTemplate getRedisTemplate() {return this.redisTemplate;}/*** 获取指定 key 的值** @param key* @return*/public String get(String key) {return redisTemplate.opsForValue().get(key);}/*** 设置指定 key 的值** @param key* @param value*/public void set(String key, String value) {redisTemplate.opsForValue().set(key, value);}
}

服务业务类提供者:
DubboTestServiceImpl:

import org.apache.dubbo.config.annotation.DubboService;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;
import org.lgx.bluegrass.api.service.DubboTestService;/*** @Description TODO* @Date 2023/2/23 15:50* @Author lgx* @Version 1.0*/
// dubbo 服务暴露标识,token = "1234" 定义token验证标识
@DubboService(token = "1234")
public class DubboTestServiceImpl implements DubboTestService {@Overridepublic ResponseDTO test(String token) {return ResponseDTO.defaultResponse("hello es"+ token);}
}

服务定义:DubboThreeService:

public interface DubboThreeService {ResponseDTO testOne(String token);
}

5) 消费端:同服务提供端1),2),3),相同 ,定义好过滤器
定义消费端token 填充:
DubboTokenFilter

public class DubboTokenFilter implements Filter {private RedisUtil redisUtil;@Overridepublic Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {if (null == redisUtil) {Object obj = ApplicationContextUtils.getBean("redisUtil");if (null != obj){redisUtil = (RedisUtil) obj;}}String isNeedToken = invoker.getUrl().getParameter(Constants.TOKEN_KEY);// 是否需要进行token 验证if (StringUtils.hasText(isNeedToken)) {// Constants.TOKEN_KEY, "1234", 便于跳过duboo 内置的token 验证// "1234" 对应服务提供端业务实现类中定义的token @DubboService(token = "1234")inv.setAttachment(Constants.TOKEN_KEY, "1234");// 设置本次真正需要验证的tokeninv.setAttachment("dubbo_accesstoken", "1234qazwsxedc");}// 远程接口调用return invoker.invoke(inv);}
}

6 ) 消费端测试:

@RestController
public class DubboRpcController {@DubboReferenceprivate DubboTestService  dubboTestService;@RequestMapping(value = "/dubbo-test", method = RequestMethod.GET)public String index(@RequestParam("token") String token) {return dubboTestService.test(token).toString();}
}

在这里插入图片描述

2 日志记录:

DubboAccessLogFilter:

import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.support.AccessLogData;import java.util.Date;/*** @Description TODO* @Date 2023/3/8 16:48* @Author lgx* @Version 1.0*/
public class DubboAccessLogFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(DubboAccessLogFilter.class);@Overridepublic Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {try {// 是否需要对改接口进行日志记录String accessLogKey = invoker.getUrl().getParameter("accesslog");if (ConfigUtils.isNotEmpty(accessLogKey)) {// 请求的数据AccessLogData logData = this.buildAccessLogData(invoker, inv);// save logsaveLog(logData);}} catch (Throwable var5) {logger.warn("Exception in AccessLogFilter of service(" + invoker + " -> " + inv + ")", var5);}return invoker.invoke(inv);}// 自行实现数据的保存private void saveLog(AccessLogData logData) {}private AccessLogData buildAccessLogData(Invoker<?> invoker, Invocation inv) {AccessLogData logData = AccessLogData.newLogData();logData.setServiceName(invoker.getInterface().getName());logData.setMethodName(inv.getMethodName());logData.setVersion(invoker.getUrl().getParameter("version"));logData.setGroup(invoker.getUrl().getParameter("group"));logData.setInvocationTime(new Date());logData.setTypes(inv.getParameterTypes());logData.setArguments(inv.getArguments());return logData;}
}

服务业务提供端:

// accesslog  日志记录标识
@DubboService(accesslog = "123")
public class DubboTestServiceTwoImpl implements DubboTestTwoService {@Overridepublic ResponseDTO sayHello() {Map<String,Object> result = new HashMap<>(1<<2);result.put("data","Hello !");result.put("success",true);result.put("code",200);return ResponseDTO.defaultResponse(result);}
}

3 数据统一封装:

AppendedFilter:

import org.apache.dubbo.rpc.*;
import org.lgx.bluegrass.api.common.dto.ResponseDTO;/*** @Description TODO* @Date 2023/3/7 11:00* @Author lgx* @Version 1.0*/
public class AppendedFilter implements Filter {@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {Result result = invoker.invoke(invocation);Result appResponse = ((AsyncRpcResult) result).getAppResponse();Object data = appResponse.getValue();if (data instanceof ResponseDTO) {return result;}// 统一进行ResponseDTO 格式数据封装返回appResponse.setValue(ResponseDTO.defaultResponse(data));return result;}
}

参考:
1 调用拦截扩展;

相关文章:

Idea+maven+spring-cloud项目搭建系列--11-2 dubbo鉴权日志记录数据统一封装

前言&#xff1a;使用dubbo做为通信组件&#xff0c;如果接口需要鉴权&#xff0c;和日志记录需要怎样处理&#xff1b; 1 鉴权&#xff1a; 1.1 在bootstrap.yml 中定义过滤器&#xff1a; dubbo.provider.filter: 过滤器的名字&#xff1a; 1.2 resources 目录下创建配置文…...

SOLIDWORKS免费培训 SW大型装配体模式课程

在SOLIDWORKS的使用过程中&#xff0c;大家经常会遇到大型装配体的处理问题&#xff0c;微辰三维的培训课程中也包含了一些大型装配体的技术培训&#xff0c;下面整理一些常见问题&#xff0c;供参考&#xff1a;大型装配体模式1.当我们打开一个大的装配体时&#xff0c;可能会…...

xxl-job registry fail

解决方法&#xff1a; 1、检查nacos是否正确&#xff0c;一定要注意格式&#xff0c;一般都是addersses的地址问题&#xff0c;一定的要加/不然找不到&#xff0c;本机就不要使用ip了&#xff0c;用localhost。 xxl: job: admin: addresses: http://localhost:8080/xxl-job-ad…...

【C#进阶】C# 反射

序号系列文章11【C#基础】C# 预处理器指令12【C#基础】C# 文件与IO13【C#进阶】C# 特性文章目录前言1&#xff0c;反射的概念2&#xff0c;使用反射访问特性3&#xff0c;反射的用途4&#xff0c;反射的优缺点比较4.1 优点&#xff1a;4.2 缺点&#xff1a;5&#xff0c;System…...

公网NAT网关与VPC NAT网关介绍与实践

NAT网关介绍 NAT网关是一种网络地址转换服务&#xff0c;提供NAT代理&#xff08;SNAT和DNAT&#xff09;能力。 公有云NAT分为公网NAT网关和VPC NAT网关。 1&#xff09;公网NAT网关&#xff1a;提供公网地址转换服务。 2&#xff09;VPC NAT网关&#xff1a;提供私网地址转换…...

Windows中UWP、WPF和Windows窗体的区别

Windows 中开发应用&#xff08;或者可以说客户端&#xff09;有三种方法&#xff1a; UWP&#xff08;Universal Windows Platform&#xff09;、WPF&#xff08;Windows Presentation Foundation&#xff09;和 Windows 窗体&#xff08;Win Forms&#xff09;。这三种方法在…...

Flink从入门到精通系列(一)

1、Flink概述 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在&#xff0c; 无边界和有边界数据流上进行有状态的计算 &#xff0c;Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算。 Apache Flink 功能强大&#xff0c;支持开发…...

云原生应用风险介绍

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/129303616 一、传统风险 传统风险主要是注入、敏感数据泄露、跨站脚本、配置错误等等&#xff0c;这些传统的安全风险在云原生应用中也是存在的&#xff0c;这里就不具体展开说了。 二、云原生应用架…...

什么是测试用例设计?

前言 想要进行测试自动化的团队都会遇到这个问题&#xff1a;自动化的成功和编码能力有多大的关联&#xff1f;现在更多的招聘信息越来越偏重于对测试人员的编程能力的要求&#xff0c;似乎这个问题的答案是极大的正关联性。 测试人员可以将编码能力用于与测试相关的各种目的…...

数据分析:基于K-近邻(KNN)对Pima人糖尿病预测分析

数据分析&#xff1a;基于K-近邻(KNN)对Pima人糖尿病预测分析 作者&#xff1a;AOAIYI 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;AOAIYI首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x…...

Kettle体系结构及源码解析

介绍 ETL是数据抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、装载&#xff08;Load&#xff09;的过程。Kettle是一款国外开源的ETL工具&#xff0c;有两种脚本文件transformation和job&#xff0c;transformation完成针对数据的基础转换&…...

大数据 | (二)SSH连接报错Permission denied

大数据 | &#xff08;三&#xff09;centos7图形界面无法执行yum命令&#xff1a;centos7图形界面无法执行yum命令 哈喽&#xff01;各位CSDN的朋友们大家好&#xff01; 今天在执行Hadoop伪分布式安装时&#xff0c;遇到了一个问题&#xff0c;在此跟大家分享&#xff0c; …...

前端——6.文本格式化标签和<div>和<span>标签

这篇文章&#xff0c;我们来讲一下HTML中的文本格式化标签 目录 1.文本格式化标签 1.1介绍 1.2代码演示 1.3小拓展 2.div和span标签 2.1介绍 2.2代码演示 2.3解释 3.小结 1.文本格式化标签 在网页中&#xff0c;有时需要为文字设置粗体、斜体和下划线等效果&#xf…...

浅谈Xpath注入漏洞

目录 知识简介 攻击简介 基础语法 语法演示 漏洞简介 漏洞原理 漏洞复现 Xpath盲注 知识简介 攻击简介 XPath注入攻击是指利用XPath 解析器的松散输入和容错特性&#xff0c;能够在 URL、表单或其它信息上附带恶意的XPath 查询代码&#xff0c;以获得权限信息的访问权…...

Oracle LogMiner分析归档日志

目录&#xff1a;Oracle LogMiner分析归档日志一、准备测试环境1、开启数据库归档日志2、打开数据库最小附加日志3、设置当前session时间日期格式二、创建测试数据1、创建数据2、数据落盘三、日志发掘测试挖掘在上次归档的Redo Log File1.确定最近归档的Redo Log File2.指定要分…...

趣味三角——第15章——傅里叶定理

第15章 傅里叶定理(Fourier’s Theorem) Fourier, not being noble, could not enter the artillery, although he was a second Newton. (傅立叶出生并不高贵&#xff0c;因此按当时的惯例进不了炮兵部队&#xff0c;虽然他是第二个牛顿。) —Franois Jean Dominique Arag…...

市场营销的核心是什么?

之所以写下「市场营销的核心是什么&#xff1f;」这篇文章&#xff0c;是因为这几天刚读完了《经理人参阅&#xff1a;市场营销》这本书。作为一个有着近十年工作经验的市场营销从业人员&#xff0c;看完这本书也产生了很多新的想法&#xff0c;也想记录一下&#xff0c;遂成此…...

c/cpp - 多线程/进程 多进程

c/cpp - 多线程/进程 多进程多进程创建多进程进程等待多进程 宏观上 两个进程完全并发的 父子进程具有互相独立的进程空间 父进程结束&#xff0c;不影响子进程的执行 创建多进程 #include <sys/types.h> #include <unistd.h> #include <stdio.h>int main()…...

MySQL必知必会 | 存储过程、游标、触发器

使用存储过程 存储过程 简单来说就是为了以后的使用而保存的一条或多条MySQL语句的集合。 我觉得就是封装了一组sql语句 为什么需要存储过程&#xff08;简单来说就是&#xff0c;简单、安全、高性能 通过把处理封装在容易使用的单元中&#xff0c;简化复杂操作所有开发人员…...

优化Facebook广告ROI的数据驱动方法:从投放到运营

“投放广告并不是最终的目的&#xff0c;关键在于如何最大程度地利用数据驱动的方法来提高广告投放的回报率&#xff08;ROI&#xff09;”Facebook广告是现代数字营销中最为常见和重要的广告形式之一。但是&#xff0c;要让Facebook广告真正发挥作用&#xff0c;需要通过数据驱…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...