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广告真正发挥作用,需要通过数据驱…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
