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广告真正发挥作用,需要通过数据驱…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...