【Nacos】 权限认证

Metadata

title: 【Nacos】 权限认证
date: 2023-01-03 22:20
tags:
  - 行动阶段/完成
  - 主题场景/组件
  - 笔记空间/KnowladgeSpace/ProgramSpace/ModuleSpace
  - 细化主题/Module/Nacos/用户指南
categories:
  - Nacos
keywords:
  - Nacos
description: 【Nacos】 权限认证

【Nacos】 权限认证

注意

  • Nacos 是一个内部微服务组件,需要在可信的内部网络中运行,不可暴露在公网环境,防止带来安全风险。
  • Nacos 提供简单的鉴权实现,为防止业务错用的弱鉴权体系,不是防止恶意攻击的强鉴权体系。
  • 如果运行在不可信的网络环境或者有强鉴权诉求,请参考官方简单实现做替换增强。

服务端如何开启鉴权

非 Docker 环境

按照官方文档配置启动, 默认是不需要登录的,这样会导致配置中心对外直接暴露。而启用鉴权之后,需要在使用用户名和密码登录之后,才能正常使用 nacos。

开启鉴权之前,application.properties 中的配置信息为:

### If turn on auth system:
nacos.core.auth.enabled=false

开启鉴权之后,application.properties 中的配置信息为:

### If turn on auth system:
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true

自定义密钥

开启鉴权之后,你可以自定义用于生成 JWT 令牌的密钥,application.properties 中的配置信息为:

### The default token(Base64 String):
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

自定义密钥时,推荐将配置项设置为 Base64 编码的字符串,且原始密钥长度不得低于 32 字符。例如下面的的例子:

### The default token(Base64 String):
nacos.core.auth.default.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=

注意:鉴权开关是修改之后立马生效的,不需要重启服务端。

Docker 环境

官方镜像

如果使用官方镜像,请在启动 docker 容器时,添加如下环境变量

NACOS_AUTH_ENABLE=true

例如,可以通过如下命令运行开启了鉴权的容器:

docker run --env PREFER_HOST_MODE=hostname --env MODE=standalone --env NACOS_AUTH_ENABLE=true -p 8848:8848 nacos/nacos-server

除此之外,还可以添加其他鉴权相关的环境变量信息:

namedescriptionoption
NACOS_AUTH_ENABLE是否开启权限系统默认: false
NACOS_AUTH_TOKEN_EXPIRE_SECONDStoken 失效时间默认: 18000
NACOS_AUTH_TOKENtoken默认: SecretKey012345678901234567890123456789012345678901234567890123456789
NACOS_AUTH_CACHE_ENABLE权限缓存开关 , 开启后权限缓存的更新默认有 15 秒的延迟默认 : false

然后运行 docker-compose 构建命令, 例如

docker-compose -f example/standalone-derby.yaml up

自定义镜像

如果选择自定义镜像,请在构建镜像之前,修改 nacos 工程中的 application.properties 文件,

将下面这一行配置信息

nacos.core.auth.enabled=false

修改为

nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true

然后再配置 nacos 启动命令。

客户端如何进行鉴权

Java SDK 鉴权

在构建 “Properties” 类时, 需传入用户名和密码。

properties.put("username","${username}");
properties.put("password","${password}");

示例代码

try {
    // Initialize the configuration service, and the console automatically obtains the following parameters through the sample code.
    String serverAddr = "{serverAddr}";
    Properties properties = new Properties();
    properties.put("serverAddr", serverAddr);

    // if need username and password to login
        properties.put("username","nacos");
        properties.put("password","nacos");

    ConfigService configService = NacosFactory.createConfigService(properties);
} catch (NacosException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

其他语言的 SDK 鉴权

待补充

Open-API 鉴权

首先需要使用用户名和密码登陆 nacos。

curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'

若用户名和密码正确, 返回信息如下:

{"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyOTE2Nn0.2TogGhhr11_vLEjqKko1HJHUJEmsPuCxkur-CfNojDo","tokenTtl":18000,"globalAdmin":true}

接下来进行配置信息或服务信息时, 应当使用该 accessToken 鉴权, 在 url 后添加参数 accessToken={accessToken}, 其中 {accessToken} 为登录时返回的 token 信息,例如

curl -X GET '127.0.0.1:8848/nacos/v1/cs/configs?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&dataId=nacos.example.1&group=nacos_group'
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&port=8848&healthy=true&ip=11.11.11.11&weight=1.0&serviceName=nacos.test.3&encoding=GBK&namespaceId=n1'

开启服务身份识别功能

开启鉴权功能后,服务端之间的请求也会通过鉴权系统的影响。考虑到服务端之间的通信应该是可信的,因此在 1.2~1.4.0 版本期间,通过 User-Agent 中是否包含 Nacos-Server 来进行判断请求是否来自其他服务端。

但这种实现由于过于简单且固定,导致可能存在安全问题。因此从 1.4.1 版本开始,Nacos 添加服务身份识别功能,用户可以自行配置服务端的 Identity,不再使用 User-Agent 作为服务端请求的判断标准。

开启方式:

### 开启鉴权
nacos.core.auth.enabled=true

### 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false

### 配置自定义身份识别的key(不可为空)和value(不可为空)
nacos.core.auth.server.identity.key=example
nacos.core.auth.server.identity.value=example

** 注意 ** 所有集群均需要配置相同的server.identity信息,否则可能导致服务端之间数据不一致或无法删除实例等问题。