1. 前言
在之前的案例中部署好Nacos
服务端后,默认没有开启鉴权,直接不用登录就能访问控制台,也能直接注册服务,存在很大的安全风险。
之前也爆过Nacos
权限认证绕过漏洞(CVE-2021-29441
):
Nacos
官方关于安全方面的一些声明:
-
Nacos
是一个内部微服务组件,需要在可信的内部网络中运行,不可暴露在公网环境,防止带来安全风险。 -
Nacos
提供简单的鉴权实现,为防止业务错用的弱鉴权体系,不是防止恶意攻击的强鉴权体系。 -
如果运行在不可信的网络环境或者有强鉴权诉求,请参考官方简单实现进行自定义插件开发。
接下来我们使用Nacos
提供的鉴权实现,对服务端进行一定的安全保护,除此之外实际应用时,Nacos
应当部署在内网,实在需要暴露在公网时,应当使用插件实现强鉴权体系。
2. 开启鉴权
2.1 服务端
服务端鉴权相关的配置在application.properties
文件中:
首先配置nacos.core.auth.enabled
为true
标识开启鉴权:
### The auth system to use, currently only 'nacos' and 'ldap' is supported:
nacos.core.auth.system.type=nacos
### 开启鉴权
nacos.core.auth.enabled=true
然后需要配置一个自定义密钥,用于生成JWT
令牌:
### The default token (Base64 String):
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
自定义秘钥注意事项:
- 在
Nacos 2.2.0.1
之后的版本,配置默认为空,需要自行添加一个,否则无法启动服务端。 - 推荐将密钥配置项设置为
Base64
编码的字符串,且原始密钥长度不得低于32
字符。 - 文档中提供的密钥为公开密钥,在实际部署时请更换为其他密钥内容,防止密钥泄漏导致安全风险。
- 密钥需要保持节点间一致,长时间不一致可能导致
403 invalid token
错误。
开启鉴权以后,在集群模式下各节点之间进行通信,需要配置白名单,通过消息头传递规定的标识,例如,在早前的版本中,携带了user-agent: nacos-server
消息头的请求,会被直接放行,但是这种方式爆出了安全漏洞。
所以Nacos
默认关闭了该配置:
### 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false
这时,就需要我们自定义一个认证Key
和Vaule
用于集群通信,示例如下:
### 配置自定义身份识别的key(不可为空)和value(不可为空)
nacos.core.auth.server.identity.key=Id-Key
nacos.core.auth.server.identity.value=Id-Value
配置完成后,重启服务端,访问控制台需要登录,默认的用户名/密码为nacos/nacos
:
在控制台中,可以对用户、角色、权限进行管理:
2.2 客户端
服务端开启鉴权后,客户端进行注册时,会报错:
Caused by: com.alibaba.nacos.api.exception.NacosException: user not found!
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.requestToServer(NamingGrpcClientProxy.java:359) ~[nacos-client-2.2.1.jar:na]
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.doSubscribe(NamingGrpcClientProxy.java:311) ~[nacos-client-2.2.1.jar:na]
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.subscribe(NamingGrpcClientProxy.java:296) ~[nacos-client-2.2.1.jar:na]
只需在application.yml
文件中添加用户名/密码即可:
spring:
application:
name: order-demo
cloud:
nacos:
discovery:
username: nacos
password: nacos
2.3 令牌缓存
无论是客户端SDK
还是OpenAPI
,都是在调用login
接口获取accessToken
之后,携带accessToken
访问服务端,服务端解析Token
进行鉴权。因此解析的动作比较耗时,如果想要提升接口的性能,可以考虑开启缓存Token
的功能,用字符串比较代替Token
解析。
服务端自2.2.1
版本后,默认鉴权插件模块支持令牌缓存功能,默认关闭,通过以下配置开启:
# 开启令牌缓存
nacos.core.auth.plugin.nacos.token.cache.enable=true
# 令牌过期时间
nacos.core.auth.plugin.nacos.token.expire.seconds=18000
在开启令牌缓存功能之后,服务端对每一个携带用户名密码访问login
接口的请求,会先检查缓存中是否存在该用户名对应的token
。若不存在,生成新的Token
,插入缓存再返回,若存在,返回该token
。