Nacos 鉴权系统源码讲解

news2024/11/15 6:42:16

目录

1. 介绍

2. Nacos SPI 鉴权机制

3. 后台管理 / HTTP 接口鉴权

4. 客户端 / GRPC 接口鉴权


1. 介绍

鉴权功能默认没有开启,开启后的效果就是 Nacos 的接口需要用户登录并且具有权限才能调用该接口。例如注册实例、发布配置等。

鉴权也就是 我是谁、我能干什么

2. Nacos SPI 鉴权机制

默认未开启鉴权,需要启用。

 

Nacos 鉴权系统使用 SPI 机制实现,这意味着用户可以自己实现扩展一个鉴权系统。Nacos 默认也提供了两个默认实现。

鉴权 SPI 接口是 com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService,所有鉴权类都实现此接口。

注释里对该接口的方法做了解释说明

 

下来看看默认实现 NacosAuthPluginService 的鉴权源码

com.alibaba.nacos.plugin.auth.impl.NacosAuthPluginService

以下只看这两个关键方法

 

validateIdentity 验证身份

下面只看关键代码:用户登录,用户登录的过程就是拿到token,然后校验token,校验通过就从token中获取到用户

 

validateIdentity 验证权限

 

3. 后台管理 / HTTP 接口鉴权

首先使用 @Secured 定义了受保护资源,然后使用 com.alibaba.nacos.core.auth.AuthFilter 进行解析处理

AuthFilter 是一个 Servlet 的 Filter,拦截了全部请求

 

接下来看看 AuthFilter 的 filter 如何实现

// com.alibaba.nacos.core.auth.AuthFilter
​
public class AuthFilter implements Filter {
    
    private final AuthConfigs authConfigs;
    
    private final ControllerMethodsCache methodsCache;
    
    private final HttpProtocolAuthService protocolAuthService;
    
    public AuthFilter(AuthConfigs authConfigs, ControllerMethodsCache methodsCache) {
        this.authConfigs = authConfigs;
        this.methodsCache = methodsCache;
        this.protocolAuthService = new HttpProtocolAuthService(authConfigs);
        this.protocolAuthService.initialize();
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        if (!authConfigs.isAuthEnabled()) {
            // 没启用鉴权,本次过滤器直接通过
            chain.doFilter(request, response);
            return;
        }
        
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        
        // 省略部分代码
        
        try {
            
            // 获取到当前请求的接口方法
            Method method = methodsCache.getMethod(req);
            
            if (method == null) {
                // 方法不存在,说明请求的是静态资源(.css,.png等),本次过滤器直接通过
                chain.doFilter(request, response);
                return;
            }
            
            if (method.isAnnotationPresent(Secured.class) && authConfigs.isAuthEnabled()) {
                // 如果当前方法上放了注解 Secured 并且 启用了鉴权功能(上面的application.properties改true的那个配置项) 就进来
                
                // 获取到 注解 Secured
                Secured secured = method.getAnnotation(Secured.class);
                if (!protocolAuthService.enableAuth(secured)) {
                    // 默认配置永远启用 auth,所以默认配置这里进不来
                    chain.doFilter(request, response);
                    return;
                }
                
                // 解析请求中的资源(从请求中到namespaceId、group、name等信息构建成一个 Resource 对象)
                Resource resource = protocolAuthService.parseResource(req, secured);
                
                // 从请求中获取到需要的 身份相关字段与值 (Authorization、accessToken、username、password)
                IdentityContext identityContext = protocolAuthService.parseIdentity(req);
                
                // 验证身份
                boolean result = protocolAuthService.validateIdentity(identityContext, resource);
                if (!result) {
                    // 验证失败抛出异常
                    throw new AccessException("Validate Identity failed.");
                }
                
                injectIdentityId(req, identityContext);
                String action = secured.action().toString();
                
                // 验证权限
                result = protocolAuthService.validateAuthority(identityContext, new Permission(resource, action));
                if (!result) {
                    // 验证失败抛出异常
                    throw new AccessException("Validate Authority failed.");
                }
            }
            chain.doFilter(request, response);
        } catch (AccessException e) {
            // 省略错误处理
        }
    }  
}

整体主流程概括下就是:获取到请求的数据、验证身份、验证权限。

鉴权功能的实现就是 验证身份验证权限 这两个功能的实现

  1. 验证身份 protocolAuthService.validateIdentity()

  1. 验证权限 protocolAuthService.validateAuthority()

看看这两个方法如何实现

// com.alibaba.nacos.auth.AbstractProtocolAuthService
​
public abstract class AbstractProtocolAuthService<R> implements ProtocolAuthService<R> {
    
    @Override
    public boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException {
        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()
                .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
        if (authPluginService.isPresent()) {
            return authPluginService.get().validateIdentity(identityContext, resource);
        }
        return true;
    }
    
    
    @Override
    public boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException {
        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()
                .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
        if (authPluginService.isPresent()) {
            return authPluginService.get().validateAuthority(identityContext, permission);
        }
        return true;
    }
​
}

解释一下

Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()
                .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());

authConfigs.getNacosAuthSystemType() 为获取到当前系统配置的 授权类型

因为鉴权系统是 SPI 机制的,所以意味着用户可以自己扩展,而默认是 Nacos 默认的实现,可以通过配置文件更改为自己实现的。

 

此时拿到了配置的授权类型 字符串 nacos

然后需要找到这个 spi 实现类

 

可以发现 SPI 接口 AuthPluginService 实现类 Nacos 实现了 2 个

LdapAuthPluginService、NacosAuthPluginService(默认)

 

就是根据这里的 authServiceName 找到了这个鉴权实现类

找到该 SPI 鉴权类后,就调用该类的方法来完成鉴权逻辑了。

4. 客户端 / GRPC 接口鉴权

客户端需要配置账号才能有权限注册服务,否则报错403 无权限

 

SpringCloud nacos 的配置

 

请求 GRPC 接口需要 传入 accessToken,accessToken 从哪里来?就是下面这段代码:

在创建 NamingFactory.createNamingService(Properties properties) 里初始化过程中,最终调用了以下 initSecurityProxy 方法

该方法内容:

  1. 创建一个可调度的1个线程的线程池

  2. 根据配置的 username password 请求 nacos server 做一次登录

  3. 可调度线程池 每5秒 定时调度任务 登录一次,也就是每隔 5 秒就请求登录接口。

 

登录方法做的就是 将 accessToken 存起来

 

由于 Nacos Client 2.x 版本之后使用的是 GRPC 请求了,所以不走 HTTP 了,那么鉴权如何实现呢

答案就是 过滤器,没错还是过滤器,不过不是 Servlet 的AuthFilter了,而是专门给 GRPC 做的过滤器。

RemoteRequestAuthFilter

 

GRPC 过滤器就是在每次接收到 GRPC 请求之后,先调用过滤器来实现的。

观察代码,发现 filter 里面的代码也是判断了 Secured 注解,判断逻辑和之前的一样

观察注册实例 GRPC 接口,也有 Secured 注解

 

此次就流程就全部走完了。

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

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

相关文章

探讨接口测试颗粒度

偶然间在论坛上看到一个帖子&#xff0c;帖子内容如下&#xff1a; 假设现在有一个新增商品的接口&#xff0c;返回的参数中有新增商品的 id&#xff08;每次返回的 id 都不一样&#xff09;、success&#xff08;判断是否成功&#xff0c;0 失败 1 成功&#xff09; 1. 接口…

代码随想录之对称二叉树

本内容来自代码随想录 使用后序遍历。 class Solution { public:bool traversal(TreeNode* left,TreeNode* right){//处理空节点情况if (left nullptr && right ! nullptr) return false;else if (left ! nullptr && right nullptr) return false;else if …

Python人工智能之混合高斯模型运动目标检测详解分析

搬运工项目&#xff0c;换个平台纪录&#xff0c;之前的广告太多 运动目标检测是计算机视觉领域中的一个重要内容&#xff0c;其检测效果将会对目标跟踪与识别造成一定的影响&#xff0c;本文将介绍用Python来进行混合高斯模型运动目标检测&#xff0c;感兴趣的朋友快来看看吧 …

4.2寸黑白红TFT电子标签【基站版】

ESL_TFT_4.2_V4 产品参数 产品型号 ESL_TFT_4.2_V4 尺寸(mm) 101.7*84.4*6.5mm 显示技术 TFT反射式 显示区域(mm) 84.8(H) * 63.6(V) 分辨率(像素) 400*300 像素尺寸(mm) 0.212x0.212 显示颜色 黑/白/红 视觉角度 45/45/60/60 工作温度 -20-70℃ 产品重量…

Spring6从入门到精通 第一章 带你玩转Spring

这里写目录标题 一 Spring框架产生的原因二 Spring6配置的关键环节 一 Spring框架产生的原因 传统的JavaWeb存在着耦合度较高的问题&#xff0c;而且实现完整的的MVC三层架构&#xff0c;开发成本过大&#xff0c;因此出现了Spring这个轻量级的开发框架&#xff0c;相当于建筑里…

C++初阶之命名空间的使用

目录 前言 命名空间的介绍 1.1 命名空间的定义 1.2 命名空间的使用 C输入&输出 总结&#xff1a; 前言 今天小编就给大家带来C的相关内容了&#xff0c;相对于C语言而言C的语法会比较复杂一点点&#xff0c;但是我相信大家通过自己的努力&#xff0c;也会很快的上手…

使用AIDEGen进行AOSP开发

什么是AIDEGen AIDEGen&#xff0c;大概是“Android IDE (helper) Generator”的简写&#xff0c;是 AOSP 源代码树中的一个工具&#xff0c;它允许从 Android Studio 等通常仅为非平台应用程序开发配置的 IDE 中处理系统应用程序。 AIDEGen 旨在自动化项目设置过程&#xff…

计算机视觉 | 八斗人工智能 (上)

目录 数字图像像素和分辨率灰度、通道和对比度其他概念 插值算法上采样和下采样的概念1. 最邻近插值2.双线性插值&#xff08;最常用&#xff09;3.双三次插值 直方图均衡化1. 灰度图直方图均衡化2. 彩色图直方图均衡化 数字图像 像素和分辨率 像素&#xff1a; 像素是分辨率…

智能营销服务性能提升2倍关键秘诀?就是亚马逊云科技

随着数字化进程加快和B2B商业市场竞争的白热化&#xff0c;通过挖掘数据“黄金”提升投资回报比与市场竞争力的智能营销&#xff0c;正成为B2B营销的热门风口。 但企业在获得更精准、更智能营销服务的同时&#xff0c;也不得不面临来自海量数据的搜寻以及数据实时更新等方面的…

Golang gorm

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly. 一 对多入门 比如要开发cmdb的系统&#xff0c;无论是硬件还是软件。硬件对应的就是对应的哪个开发在用。或者服务对应的是哪个业务模块在使用&#xff0c;或者应用谁在使用。那么这…

【CXL】在gem5中跑一个实际的应用程序——Viper KV存储

有了CXL扩展内存&#xff0c;自然是要在DRAMCXL扩展内存上跑跑实际的应用程序&#xff0c;看看和DRAM传统磁盘有什么区别。 实际的应用程序其实就是一些工业界部署使用的&#xff0c;比如数据库、深度学习训练项目等等。本文主要找到一个KV存储Viper&#xff0c;搭建并进行简单…

水电设计院信息管理系统1.0

水电设计公司信息管理系统软件使用说明书 代码太多就不贴了&#xff0c;请在我的资源里下载&#xff0c;已部署在企业进行试运行。https://download.csdn.net/download/weixin_44735475/87704302 目录 1.引言 1 2.项目背景 1 3.系统功能 2 3.1系统功能 2 3.2系统性能 2 3.3系…

Python GUI自动化神器pyautogui,精准识别图片并自动点赞(32)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 你听过GUI自动化吗&#xff1f; GUI自动化就是用软件模拟鼠标和键盘的操作。 提到Python GUI自动化&#xff0c;不…

Flink State 笔记帖

1 State 分类 Operator State 主要用在Source、Sink等没有key分布的位置。 Keyed State 用在keyBy后的KeyedStream里&#xff0c;每个存储状态与一个key想关联。 ValueState ListState MapState ReducingState AggeratingState 2 State Backend StateBackend分类 HashMa…

JVM之JDK 监控和故障处理工具总结

JDK 命令行工具 这些命令在 JDK 安装目录下的 bin 目录下&#xff1a; jps (JVM Process Status&#xff09;: 类似 UNIX 的 ps 命令。用于查看所有 Java 进程的启动类、传入参数和Java 虚拟机参数等信息&#xff1b;jstat&#xff08;JVM Statistics Monitoring Tool&#x…

虚拟人与娱乐传媒融合,推动综艺新模式

经过多年的更新迭代和市场的推动&#xff0c;虚拟人技术正在逐渐迈向成熟&#xff1a;3D虚拟形象的制作变得越来越精致且真实&#xff0c;并且出现了越来越多功能丰富使用便捷的动捕设备。因此&#xff0c;包括综艺影视在内的诸多领域&#xff0c;开始尝试将虚拟人技术融入行业…

DETR:end-to-end object detection with transformers

DETR 论文精读【论文精读】_哔哩哔哩_bilibili更多论文&#xff1a;https://github.com/mli/paper-reading/, 视频播放量 90699、弹幕量 493、点赞数 3566、投硬币枚数 2939、收藏人数 2564、转发人数 663, 视频作者 跟李沐学AI, 作者简介 &#xff0c;相关视频&#xff1a;在线…

【设计原则】依赖倒置原则--高层代码和底层代码到底谁该依赖谁?

文章目录 前言一、谁依赖谁二、依赖于抽象总结 前言 依赖这个词&#xff0c;程序员们都好理解&#xff0c;意思就是&#xff0c;我这段代码用到了谁&#xff0c;我就依赖了谁。依赖容易有&#xff0c;但能不能把依赖弄对&#xff0c;就需要动点脑子了。 如果依赖关系没有处理…

【红队APT】反朔源隐藏C2项目CDN域前置云函数数据中转DNS转发

文章目录 域前置-CDN隐藏C2真实IP 防止被溯源什么是域前置条件原理 完整复现域前置溯源 DNS协议-域名记录解析云函数-腾讯云操作云函数如何溯源 端口转发-Iptables中间件反向代理-Apache 域前置-CDN隐藏C2真实IP 防止被溯源 国内外云服务上大部分已经不支持域前置了&#xff0…

局域网哪些特点?快解析内网穿透实现外网访问局域网SVN

无线局域网传统是有线局域网络的补充和扩展&#xff0c;具有灵活性、可移动性及较低的投资成本等优势&#xff0c;受到了家庭网络用户、中小型办公室用户、广大企业用户及电信运营商的青睐&#xff0c;成为当前整个数据通信领域发展最快的产业之一。 局域网一般为一个单位所建&…