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鉴权日志记录数据统一封装
前言:使用dubbo做为通信组件,如果接口需要鉴权,和日志记录需要怎样处理; 1 鉴权: 1.1 在bootstrap.yml 中定义过滤器: dubbo.provider.filter: 过滤器的名字: 1.2 resources 目录下创建配置文…...
SOLIDWORKS免费培训 SW大型装配体模式课程
在SOLIDWORKS的使用过程中,大家经常会遇到大型装配体的处理问题,微辰三维的培训课程中也包含了一些大型装配体的技术培训,下面整理一些常见问题,供参考:大型装配体模式1.当我们打开一个大的装配体时,可能会…...
xxl-job registry fail
解决方法: 1、检查nacos是否正确,一定要注意格式,一般都是addersses的地址问题,一定的要加/不然找不到,本机就不要使用ip了,用localhost。 xxl: job: admin: addresses: http://localhost:8080/xxl-job-ad…...
【C#进阶】C# 反射
序号系列文章11【C#基础】C# 预处理器指令12【C#基础】C# 文件与IO13【C#进阶】C# 特性文章目录前言1,反射的概念2,使用反射访问特性3,反射的用途4,反射的优缺点比较4.1 优点:4.2 缺点:5,System…...
公网NAT网关与VPC NAT网关介绍与实践
NAT网关介绍 NAT网关是一种网络地址转换服务,提供NAT代理(SNAT和DNAT)能力。 公有云NAT分为公网NAT网关和VPC NAT网关。 1)公网NAT网关:提供公网地址转换服务。 2)VPC NAT网关:提供私网地址转换…...
Windows中UWP、WPF和Windows窗体的区别
Windows 中开发应用(或者可以说客户端)有三种方法: UWP(Universal Windows Platform)、WPF(Windows Presentation Foundation)和 Windows 窗体(Win Forms)。这三种方法在…...
Flink从入门到精通系列(一)
1、Flink概述 Apache Flink 是一个框架和分布式处理引擎,用于在, 无边界和有边界数据流上进行有状态的计算 ,Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。 Apache Flink 功能强大,支持开发…...
云原生应用风险介绍
本博客地址:https://security.blog.csdn.net/article/details/129303616 一、传统风险 传统风险主要是注入、敏感数据泄露、跨站脚本、配置错误等等,这些传统的安全风险在云原生应用中也是存在的,这里就不具体展开说了。 二、云原生应用架…...
什么是测试用例设计?
前言 想要进行测试自动化的团队都会遇到这个问题:自动化的成功和编码能力有多大的关联?现在更多的招聘信息越来越偏重于对测试人员的编程能力的要求,似乎这个问题的答案是极大的正关联性。 测试人员可以将编码能力用于与测试相关的各种目的…...
数据分析:基于K-近邻(KNN)对Pima人糖尿病预测分析
数据分析:基于K-近邻(KNN)对Pima人糖尿病预测分析 作者:AOAIYI 作者简介:Python领域新星作者、多项比赛获奖者:AOAIYI首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞&#x…...
Kettle体系结构及源码解析
介绍 ETL是数据抽取(Extract)、转换(Transform)、装载(Load)的过程。Kettle是一款国外开源的ETL工具,有两种脚本文件transformation和job,transformation完成针对数据的基础转换&…...
大数据 | (二)SSH连接报错Permission denied
大数据 | (三)centos7图形界面无法执行yum命令:centos7图形界面无法执行yum命令 哈喽!各位CSDN的朋友们大家好! 今天在执行Hadoop伪分布式安装时,遇到了一个问题,在此跟大家分享, …...
前端——6.文本格式化标签和<div>和<span>标签
这篇文章,我们来讲一下HTML中的文本格式化标签 目录 1.文本格式化标签 1.1介绍 1.2代码演示 1.3小拓展 2.div和span标签 2.1介绍 2.2代码演示 2.3解释 3.小结 1.文本格式化标签 在网页中,有时需要为文字设置粗体、斜体和下划线等效果…...
浅谈Xpath注入漏洞
目录 知识简介 攻击简介 基础语法 语法演示 漏洞简介 漏洞原理 漏洞复现 Xpath盲注 知识简介 攻击简介 XPath注入攻击是指利用XPath 解析器的松散输入和容错特性,能够在 URL、表单或其它信息上附带恶意的XPath 查询代码,以获得权限信息的访问权…...
Oracle LogMiner分析归档日志
目录: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. (傅立叶出生并不高贵,因此按当时的惯例进不了炮兵部队,虽然他是第二个牛顿。) —Franois Jean Dominique Arag…...
市场营销的核心是什么?
之所以写下「市场营销的核心是什么?」这篇文章,是因为这几天刚读完了《经理人参阅:市场营销》这本书。作为一个有着近十年工作经验的市场营销从业人员,看完这本书也产生了很多新的想法,也想记录一下,遂成此…...
c/cpp - 多线程/进程 多进程
c/cpp - 多线程/进程 多进程多进程创建多进程进程等待多进程 宏观上 两个进程完全并发的 父子进程具有互相独立的进程空间 父进程结束,不影响子进程的执行 创建多进程 #include <sys/types.h> #include <unistd.h> #include <stdio.h>int main()…...
MySQL必知必会 | 存储过程、游标、触发器
使用存储过程 存储过程 简单来说就是为了以后的使用而保存的一条或多条MySQL语句的集合。 我觉得就是封装了一组sql语句 为什么需要存储过程(简单来说就是,简单、安全、高性能 通过把处理封装在容易使用的单元中,简化复杂操作所有开发人员…...
优化Facebook广告ROI的数据驱动方法:从投放到运营
“投放广告并不是最终的目的,关键在于如何最大程度地利用数据驱动的方法来提高广告投放的回报率(ROI)”Facebook广告是现代数字营销中最为常见和重要的广告形式之一。但是,要让Facebook广告真正发挥作用,需要通过数据驱…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
