基于Spring Boot + Nacos + Dubbo自定义鉴权过滤器实现方案解析

 更新时间:2026年02月03日 10:09:05   作者:xiaoye3708  
本文介绍了基于SpringBoot+Nacos+Dubbo的自定义鉴权过滤器实现方案,介绍了如何通过Nacos配置中心实现鉴权规则的动态配置,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

实现说明

  1. 整体流程

    • 服务提供者启动时会注册到 Nacos,并启用自定义的AuthFilter
    • 客户端调用服务前,通过RpcContext设置鉴权信息(token 和应用名)
    • 服务端的AuthFilter会拦截请求,验证鉴权信息
    • 验证通过则继续调用,否则抛出异常
  2. 关键实现点

    • 使用@Activate注解指定过滤器在服务端生效
    • 通过 SPI 机制注册过滤器
    • invoke方法中实现鉴权逻辑
    • 利用RpcContext传递和获取调用上下文信息
  3. 动态配置

    • 进阶实现中添加了 Nacos 配置中心客户端
    • 可以动态获取和更新鉴权规则,无需重启服务

使用时,需要先启动 Nacos 服务器,然后分别启动服务提供者和消费者,即可看到鉴权效果。你可以根据实际业务需求修改validateTokenhasMethodPermission方法中的鉴权逻辑。

1.自定义鉴权过滤器实现

package com.example.dubbo.filter;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.stereotype.Component;
/**
 * 基于Dubbo SPI的自定义鉴权过滤器
 */
@Activate(group = CommonConstants.PROVIDER, order = 100) // 仅在服务端生效
@Component
public class AuthFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        // 1. 从上下文获取调用信息
        RpcContext context = RpcContext.getContext();
        String token = context.getAttachment("auth_token");
        String appName = context.getAttachment("app_name");
        String clientIp = context.getRemoteHost();
        String methodName = invocation.getMethodName();
        // 2. 打印调用信息
        System.out.println("收到调用请求 - 方法: " + methodName + ", 客户端IP: " + clientIp + ", 应用名: " + appName);
        // 3. 执行鉴权逻辑
        if (!validateToken(token, appName)) {
            throw new RpcException("鉴权失败: 无效的token或应用名");
        }
        // 4. 检查方法级权限
        if (!hasMethodPermission(appName, methodName)) {
            throw new RpcException("权限不足: 应用" + appName + "没有调用" + methodName + "方法的权限");
        }
        // 5. 鉴权通过,继续执行调用
        return invoker.invoke(invocation);
    }
    /**
     * 验证token有效性
     */
    private boolean validateToken(String token, String appName) {
        // 实际项目中,这里应该从Nacos配置中心或数据库获取有效token列表
        // 简单示例:验证token格式和应用名
        if (token == null || appName == null) {
            return false;
        }
        // 从Nacos获取配置的有效应用和token映射关系
        // 这里简化处理,实际应通过NacosConfigService获取
        return "valid_token_123".equals(token) && "authorized_app".equals(appName);
    }
    /**
     * 检查是否有方法调用权限
     */
    private boolean hasMethodPermission(String appName, String methodName) {
        // 实际项目中,这里应该从Nacos配置中心获取应用与方法的权限映射
        // 简单示例:只有特定应用可以调用敏感方法
        if ("deleteUser".equals(methodName) && !"admin_app".equals(appName)) {
            return false;
        }
        return true;
    }
}

2.创建 SPI 配置文件,让 Dubbo 能够发现我们的过滤器:

# 注册自定义鉴权过滤器
authFilter=com.example.dubbo.filter.AuthFilter

3.服务提供者配置

application.yml

spring:
  application:
    name: dubbo-auth-provider
dubbo:
  application:
    name: dubbo-auth-provider
  registry:
    address: nacos://127.0.0.1:8848  # Nacos注册中心地址
    username: nacos                  # Nacos用户名
    password: nacos                  # Nacos密码
  protocol:
    name: dubbo
    port: 20880
  provider:
    filter: authFilter               # 启用自定义鉴权过滤器
    timeout: 3000
# Nacos配置中心
nacos:
  config:
    server-addr: 127.0.0.1:8848
    namespace: public

4.服务接口和实现

package com.example.dubbo.service;
public interface UserService {
    String getUserInfo(Long id);
    String deleteUser(Long id);
}
package com.example.dubbo.service.impl;
import com.example.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
@DubboService(interfaceClass = UserService.class)
public class UserServiceImpl implements UserService {
    @Override
    public String getUserInfo(Long id) {
        return "User info for id: " + id + ", name: testUser";
    }
    @Override
    public String deleteUser(Long id) {
        return "User " + id + " deleted successfully";
    }
}

服务消费者配置和代码

package com.example.dubbo.consumer;
import com.example.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ConsumerApplication {
    @DubboReference
    private UserService userService;
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    @Bean
    public ApplicationRunner runner() {
        return args -> {
            // 调用前设置鉴权信息
            RpcContext.getContext()
                    .setAttachment("auth_token", "valid_token_123")
                    .setAttachment("app_name", "authorized_app");
            // 调用普通方法
            String userInfo = userService.getUserInfo(1L);
            System.out.println("调用结果: " + userInfo);
            // 尝试调用需要管理员权限的方法
            try {
                String deleteResult = userService.deleteUser(1L);
                System.out.println("删除结果: " + deleteResult);
            } catch (Exception e) {
                System.out.println("调用deleteUser方法失败: " + e.getMessage());
            }
        };
    }
}

从 Nacos 配置中心获取鉴权规则

package com.example.dubbo.config;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import java.util.concurrent.Executor;
@Configuration
public class NacosConfig {
    @Value("${nacos.config.server-addr}")
    private String serverAddr;
    @Value("${nacos.config.namespace}")
    private String namespace;
    @Bean
    public ConfigService configService() throws NacosException {
        Properties properties = new Properties();
        properties.put("serverAddr", serverAddr);
        properties.put("namespace", namespace);
        ConfigService configService = NacosFactory.createConfigService(properties);
        // 监听鉴权规则配置变化
        String dataId = "dubbo-auth-rules";
        String group = "DEFAULT_GROUP";
        configService.addListener(dataId, group, new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                System.out.println("收到新的鉴权规则配置: " + configInfo);
                // 更新本地缓存的鉴权规则
                AuthRuleCache.updateRules(configInfo);
            }
            @Override
            public Executor getExecutor() {
                return null;
            }
        });
        // 初始化加载配置
        String config = configService.getConfig(dataId, group, 5000);
        if (config != null) {
            AuthRuleCache.updateRules(config);
        }
        return configService;
    }
}
// 鉴权规则缓存类
class AuthRuleCache {
    private static String authRules;
    public static void updateRules(String rules) {
        authRules = rules;
        // 这里可以解析规则并存储到内存中
    }
    public static String getAuthRules() {
        return authRules;
    }
}

到此这篇关于基于 Spring Boot + Nacos + Dubbo 的完整自定义鉴权过滤器实现方案的文章就介绍到这了,更多相关springboot nacos dubbo自定义鉴权过滤器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于RestTemplate的使用深度解析

    关于RestTemplate的使用深度解析

    这篇文章主要介绍了对RestTemplate的深度解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • mybatis-plus 处理大数据插入太慢的解决

    mybatis-plus 处理大数据插入太慢的解决

    这篇文章主要介绍了mybatis-plus 处理大数据插入太慢的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 浅析SpringBoot整合Mybatis如何实现二级缓存

    浅析SpringBoot整合Mybatis如何实现二级缓存

    二级缓存,是指多个Sqlsession之间共享数据,但是也可以使用Redis这样的缓存作为存储点,但是不支持mybatisplus 里的方法,本文我们就来聊聊SpringBoot整合Mybatis实现二级缓存的相关方法吧
    2025-05-05
  • java实现文件上传下载至ftp服务器

    java实现文件上传下载至ftp服务器

    这篇文章主要为大家详细介绍了java实现文件上传下载至ftp服务器的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 从Java的jar文件中读取数据的方法

    从Java的jar文件中读取数据的方法

    这篇文章主要介绍了从Java的jar文件中读取数据的方法,实例分析了java档案文件的相关操作技巧,需要的朋友可以参考下
    2015-06-06
  • spring AOP的Around增强实现方法分析

    spring AOP的Around增强实现方法分析

    这篇文章主要介绍了spring AOP的Around增强实现方法,结合实例形式分析了spring面向切面AOP的Around增强具体步骤与相关操作方法,需要的朋友可以参考下
    2020-01-01
  • Java单链表的增删改查与面试题详解

    Java单链表的增删改查与面试题详解

    单链表是链表的其中一种基本结构。一个最简单的结点结构如图所示,它是构成单链表的基本结点结构。在结点中数据域用来存储数据元素,指针域用于指向下一个具有相同结构的结点。 因为只有一个指针结点,称为单链表
    2022-09-09
  • mybatis解析xml配置中${xxx}占位符的代码逻辑

    mybatis解析xml配置中${xxx}占位符的代码逻辑

    本文主要介绍了mybatis解析xml配置中${xxx}占位符的代码逻辑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2023-05-05
  • Spring与bean有关的生命周期示例详解

    Spring与bean有关的生命周期示例详解

    这篇文章主要给大家介绍了关于Spring与bean有关的生命周期的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • Java实现创建Zip压缩包并写入文件

    Java实现创建Zip压缩包并写入文件

    这篇文章主要为大家详细介绍了Java实现创建Zip压缩包并写入文件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论