🙈 By 陈潞波 2024-03-29
1.需求
当前仅仅支持auth_basic_user_file,需要手工修改 file的内容增加新的用户,修改密码。 需添加一种类型: auth_basic_kv,利用kv存储用户名/密码
•key为 “auth_basic”:{prefix}:{user_name}, value 为 密码。 prefix支持变量,以便使用server_name等,方便配置。
•提供HTTP接口,实现动态增加条目,或修改密码,也支持删除
2.auth_basic_kv 指令设计
该指令可配置在main, server, location, limit_conf 块中以api_limit_except为例进行说明 auth_basic_kv指令放在 njt_http_auth_basic_module 模块中,与auth_basic_user_file 指令配置二选一,不可同时配置
Syntax | auth_basic_kv {prefix} |
Default | - |
Context | main,server,location,limit_conf |
prefix 即可为变量也可为普通字符串 kv存储的实际密码格式为: Key: auth_basic:{prefix}:{user_name} Value: 密码 (采用SHA算法)
Eg:
•假设用户名为njet, 使用变量 $server_name格式,(如果实际server_name 为www.baidu.com)则kv内存实际存储为: Key: auth_basic:www.baidu.com:njet
•假设用户名为njet, 使用固定字符串test_prefix格式,则kv内存实际存储为: Key: auth_basic:test_prefix:njet
#变量格式
api_limit_except GET {
auth_basic "OpenNJet AUTH API";
auth_basic_kv $server_name;
}
#字符串格式
api_limit_except GET {
auth_basic "OpenNJet AUTH API";
auth_basic_kv test_prefix;
}
NOTE:
Http 请求到来时,如果是变量,则会将变量转化为实际的值,然后再去kv db里查找,故kv db里存储的都是实际的变量取值而不是变量
3. 密码 http api接口设计
新增一个 njt_http_auth_api_module, 同其他命令式api 模块一样(控制面通过/api 入口配置),提供http api接口,提供密码增删改功能 统一前缀: /api/v1/auth_kv/{type} type:[password|role|login] 预留,目前时就password类型操作密码, 以后可以操作role角色以及login登陆
3.1 设置密码接口:
PUT:/api/v1/auth_kv/password body如下格式:
{
"prefix": "www.baidu.com", #对应上面$server_name变量,此处是实际的变量取值
"user_name": "njet",
"password": "123456"
}
或者
{
"prefix": "test_prefix", #此处是明确的字符串前缀
"user_name": "njet",
"password": "123456"
}
错误码 | 错误提示 | |
---|---|---|
增加成功 | 0 | success |
用户已存在 | 4 | user existed |
增加失败 | 4 | add password error |
参数有空值 | 3 | prefix,user_name and password should not be empty |
参数不合法 | 3 | 会有具体json错误 |
密码加密失败 | 4 | password encrypt error |
3.2 修改密码接口:
PATCH:/api/v1/auth_kv/password/{prefix}/{user_name}
#变量取值
/api/v1/auth_kv/password/www.baidu.com/njet
或者
#明确字符串前缀
/api/v1/auth_kv/password/test_prefix/njet
body如下格式:
{
"password": "123456"
}
错误码 | 错误提示 | |
---|---|---|
修改成功 | 0 | success |
用户不存在 | 4 | user is not existed |
修改失败 | 4 | modify password error |
参数有空值 | 3 | prefix,user_name and password should not be empty |
参数不合法 | 3 | 会有具体json错误 |
密码加密失败 | 4 | password encrypt error |
3.3 删除密码接口:
DELETE:/api/v1/auth_kv/password/{prefix}/{user_name}
#变量取值
/api/v1/auth_kv/password/www.baidu.com/njet
或者
#明确字符串前缀
/api/v1/auth_kv/password/test_prefix/njet
返回值
错误码 | 错误提示 | |
---|---|---|
用户成功删除 | 0 | success |
用户不存在 | 4 | user is not exist |
用户删除失败 | 4 | delete error |
4. 测试
4.1 测试配置(以控制面配置 api_limit_except块测试为例):
为range api 接口添加权限验证为例进行测试(固定字符串前缀) 为ssl api 接口添加权限验证为例进行测试(使用变量前缀)
ctrl.conf
...
load_module modules/njt_http_range_api_module.so; #以range api 设置权限验证普通字符串前缀为例测试
load_module modules/njt_http_ssl_api_module.so; #以range api 设置权限验证变量前缀为例测试
load_module modules/njt_http_auth_api_module.so; #auth kv 模块加载
...
http {
server {
listen 8081;
server_name www.test.com; #下面使用$server_name变量测试
location /api {
dyn_module_api;
api_limit_except /v1/range PUT {
auth_basic "OpenNJet range API";
auth_basic_kv test_kv; #range 使用固定前缀字符串测试
}
api_limit_except /v1/ssl PUT {
auth_basic "OpenNJet ssl API";
auth_basic_kv $server_name; #ssl 使用变量前缀测试
}
}
location /doc {
doc_api;
}
}
}
4.2 range 固定字符串前缀测试(用户名:njet 密码123456)
PUT 增加用户名密码测试 初始不存在njet用户以及密码123456 访问range api get接口,提示输入密码,输入njet/123456 , 校验不通过
通过auth 配置去配置用户名密码, njet/123456
再次访问range get 接口,输入 njet/123456, 成功验证通过
PATCH 修改密码测试
重新访问range get接口,使用 njet/12345 不通过
使用njet/654321, 验证通过
DELETE 删除密码测试 删除密码
再次访问range, 不通过
4.3 ssl 使用变量前缀测试(用户名:ssl 密码123456)
PUT 增加用户名密码测试 初始不存在ssl 用户以及密码123456 访问range ssl get接口,提示输入密码,输入ssl/123456 , 校验不通过
通过auth 配置去配置用户名密码, ssl/123456, 前缀使用www.test.com
再次访问ssl get 接口,输入 ssl/123456, 成功验证通过
PATCH 修改密码测试 重新访问ssl get接口,使用 ssl/12345 不通过
使用ssl/654321, 验证通过
DELETE 删除密码测试 删除密码
再次访问ssl, 不通过