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

news2024/11/26 3:45:47

前言:使用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;
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String isNeedToken = invoker.getUrl().getParameter(Constants.TOKEN_KEY);
        // 是否需要进行token 验证
        if (StringUtils.hasText(isNeedToken)) {
        	// 获取消费端传入的token
            String clientToken1 = invocation.getAttachment("dubbo_accesstoken");
            // 获取服务端的token
            String 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 {
    @Override
    public 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;

    @Override
    public 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");
            // 设置本次真正需要验证的token
            inv.setAttachment("dubbo_accesstoken", "1234qazwsxedc");
        }
        // 远程接口调用
        return invoker.invoke(inv);
    }
}

6 ) 消费端测试:

@RestController
public class DubboRpcController {
	 @DubboReference
    private 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);
    @Override
    public 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 log
                saveLog(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 {
    @Override
    public 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 {
    @Override
    public 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 调用拦截扩展;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/401166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

随笔:车辆游戏功能开发-思路

目录1 博客内容2 PS4pro3 功能开发1 博客内容 年初朋友聊天谈到车辆增加G&#xff08;Game&#xff09;挡位&#xff0c;适配泛娱乐化功能。均非该领域人员&#xff0c;上月他也离开去无锡&#xff0c;同时该功能涉及悬架、座椅、HUT、音响、转向、线控底盘等多专业人员&#x…

深信服校园招聘安全攻防F卷

1.请尽可能列举你知道的网站未能正确使用图片验证码机制的情况&#xff0c;以及如何绕过其限制&#xff1f; - 图形验证码的内容可OCR识别 - 多阶段的过程&#xff0c;先校验验证码&#xff0c;成功之后的下一步不需要验证码&#xff0c;可以直接抓包&#xff0c;跳过第一步的验…

小诺开源技术

小诺开源技术 文章目录小诺开源技术前言页面演示介绍文档学习建议登录地址下载地址前言 近期接触了小诺开源技术的一个前端框架&#xff0c;底层是蚂蚁框架&#xff0c;感觉很好用&#xff0c;不过需要稍微学习并适应一下&#xff0c;推荐给大家&#xff0c;本篇仅用于学习&am…

人员摔倒识别预警算法 opencv

人员摔倒识别预警算法通过opencv网络模型技术&#xff0c;人员摔倒识别预警算法能够智能检测现场画面中人员有没有摔倒&#xff0c;无需人为干预可以立刻抓拍告警。OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台的计算机视觉处理开源软件库&…

C#:Krypton控件使用方法详解(第十四讲) ——kryptonSeparator

今天介绍的Krypton控件中的kryptonSeparator。下面介绍控件的外观属性如下图所示&#xff1a;Cursor属性&#xff1a;表示鼠标移动过该控件的时候&#xff0c;鼠标显示的形状。属性值如下图所示&#xff1a;DrawMoveIndicator属性&#xff1a;表示确定移动分隔符时是否绘制移动…

要不做一名 Prompt Engineer

文章目录1. 什么是 Prompt Engineer2. 如何成为 Prompt Engineer3. Prompt Engineer 需要具备哪些技能4. Prompt Egnineer 适合什么工作岗位5. Prompt Egnineer 未来的发展趋势&#xff1f;6. 哪些公司正在招聘 Prompt Egineer7. Prompt Engineer 必备的20个工具8. Prompt Engi…

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

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

量化派递交上市申请,数字经济风口上开启“狂飙”模式

今年全国两会&#xff0c;代表委员们纷纷围绕“中小企业数字化转型”建言献策。如全国政协委员、甘肃省工业和信息化厅副厅长黄宝荣建议&#xff0c;在工业领域加快数字经济立法&#xff0c;支撑中小企业数字化转型&#xff1b;全国政协委员、中国财政科学研究院院长刘尚希建议…

智能移动出行带来更美好的未来——美国智能交通协会交通政策(附下载)

美国智能交通协会&#xff08;ITS America&#xff09;是美国交通系统技术现代化的国家主要倡导者&#xff0c;专注于推进智能交通技术的研究和部署。美国智能交通协会是美国交通部道路技术的官方咨询委员会&#xff0c;代表州和城市交通部门&#xff0c;运输部门&#xff0c;大…

佩戴舒适的蓝牙耳机品牌有哪些?不伤耳朵的蓝牙耳机推荐

现在不少人都离不开耳机吧&#xff1f;但什么样的耳机才是安全的、不伤耳的&#xff1f;更多的人看重耳机的重量&#xff0c;但是否贴合耳廓也是十分重要的&#xff0c;下面整理了几款当前热销佩戴舒适的蓝牙耳机&#xff0c;可供大家选购参考。 第一款&#xff1a;南卡小音舱蓝…

通达信捉妖改良CCI指标公式,简洁巧妙

高端的食材&#xff0c;往往只需要简单的烹饪方式。好的指标也是一样&#xff0c;只需要简单处理&#xff0c;就可以实现不错的效果。捉妖改良CCI指标公式属于意外之喜&#xff0c;编写指标时写错了&#xff0c;研究后发现结果比原想法更好。 捉妖改良CCI指标公式利用了CCI&am…

Python每日一练(20230310)

目录 1. 爬楼梯 ★ 2. 删除无效的括号 ★★★ 3. 给表达式添加运算符 ★★★ &#x1f31f; 每日一练刷题专栏 C/C 每日一练 ​专栏 Python 每日一练 专栏 1. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方…

分隔链表(精美图示详解哦)

全文目录引言分隔链表题目描述与思路实现总结引言 前面&#xff0c;我们熟悉了管理链表中的数据的方法&#xff0c;也了解了几道与链表相关的题目&#xff1a; 戳我看单链表详解哦 在本篇文章中&#xff0c;我们将再了解一道题目&#xff1a;分隔链表&#xff1a; 分隔链表OJ…

【Python】用Python实现帕累托图

作为一名多次创业者和项目管理培训师&#xff0c; 今天田辛老师要做一件跨界的事情。 一方面&#xff0c; 田老师整理了项目管理中的重要质量管理工具 “帕累托图”&#xff0c; 另一方面&#xff0c;田老师给到了帕累托图的Python的实现方式。 如果您只对Python实现方式感兴趣…

思科模拟器 | 交换机与路由器的配置汇总【收藏备用】

文章目录一、vlan配置【实现同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、测试连接二、truck配置【实现连接在不同交换机上的同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、打truck做连接3、测试连接三、静态路由配置1、自定义IP地址2、基本…

品牌营销 | 学习如何最大限度地发挥品牌营销的作用

您是否想过如何最大限度地发挥品牌营销的潜力&#xff1f;这是一项艰巨的挑战&#xff0c;通过了解品牌营销的基本组成部分&#xff0c;您可以成功地推广您的品牌。 &#xff08;图源&#xff1a;Pixabay&#xff09; 品牌营销的基本组成部分 你需要做什么来发展稳固的品牌&am…

STC89C51单片机相比于其他单片机具有那些优点?

STC89C51只适合和同性能的51内核单片机相比&#xff0c;性能不同并无可比性。11年前&#xff0c;我就是通过自学STC89C51入行单片机开发的。到目前为止都非常经典&#xff0c;很多开发板都是基于这个芯片去做的。我对STC单片机也是比较有好感的&#xff0c;一般51单片机的产品基…

【Java|golang】2379. 得到 K 个黑块的最少涂色次数---滑动窗口

给你一个长度为 n 下标从 0 开始的字符串 blocks &#xff0c;blocks[i] 要么是 ‘W’ 要么是 ‘B’ &#xff0c;表示第 i 块的颜色。字符 ‘W’ 和 ‘B’ 分别表示白色和黑色。 给你一个整数 k &#xff0c;表示想要 连续 黑色块的数目。 每一次操作中&#xff0c;你可以选…

07 C语言数组

07 C语言数组 1、初试数组 #include<stdio.h>int main(int argc,char const *argv[]){double sum;int a[100];int i 0;int cnt 0;scanf("%d",&i);while(i ! -1){sum i;a[cnt] i;scanf("%d",&i);}if(cnt > 0){double average sum / …

深入堆空间

堆空间用来干嘛的&#xff1f;我们知道基础类型的变量、对象的引用既可以在栈也可以在堆上&#xff0c;但是对象一定是在堆空间的。堆上存储的是从GC Root可达的活跃对象。什么是GC Root&#xff1f;垃圾回收器在判断哪些对象该回收的时候&#xff0c;需要一个标准&#xff0c;…