PLSQL中令牌认证运作原理及无密钥实现方案咨询(非Apex环境)
PLSQL实现REST服务令牌认证方案解析
一、PLSQL中令牌认证的运作方式
你遇到的是预颁发短期令牌模式,核心流程如下:
- 从服务提供商处获取有效期15分钟的令牌(可通过专用接口自动获取,或服务商手动发放);
- 每次调用目标REST API时,将令牌放入HTTP请求的
Authorization头部,格式固定为Bearer <令牌内容>; - 服务端收到请求后,自行验证令牌的有效性与有效期,验证通过则允许接口访问。
和之前的基础认证区别在于:基础认证每次请求都携带编码后的用户名密码,而令牌认证仅需携带预生成的令牌,避免了敏感凭证的频繁传输。
二、是否需要知晓服务端算法、必须使用密钥?
完全不需要。AS_CRYPTO这类包是用于本地生成签名令牌的场景(比如自行生成JWT并签名),但你的场景是服务端直接提供生成好的令牌,你只负责在请求中携带它即可,无需参与令牌的生成、签名过程,因此不需要了解服务端使用的算法,也不需要用到公钥、私钥。
三、不使用Apex的PLSQL实现方案
直接用Oracle自带的UTL_HTTP包即可实现,无需依赖Apex,分两步操作:
1. 获取令牌(以接口自动获取为例)
如果服务商提供令牌获取接口,用以下代码调用获取:
DECLARE l_req UTL_HTTP.REQ; l_res UTL_HTTP.RESP; l_token VARCHAR2(4000); l_buffer VARCHAR2(4000); BEGIN -- 初始化令牌请求 l_req := UTL_HTTP.BEGIN_REQUEST('https://服务商令牌接口地址', 'POST'); UTL_HTTP.SET_HEADER(l_req, 'Content-Type', 'application/x-www-form-urlencoded'); -- 发送获取令牌所需的凭证(根据服务商要求调整参数) UTL_HTTP.WRITE_TEXT(l_req, 'username=你的账号&password=你的密码'); -- 处理响应,提取令牌 l_res := UTL_HTTP.GET_RESPONSE(l_req); WHILE UTL_HTTP.END_OF_RESPONSE(l_res) = FALSE LOOP UTL_HTTP.READ_TEXT(l_res, l_buffer, 4000); -- 假设响应是JSON格式,用JSON_VALUE解析令牌字段 l_token := JSON_VALUE(l_buffer, '$.token'); END LOOP; UTL_HTTP.END_RESPONSE(l_res); -- 可将令牌存入数据库表或变量,供后续调用使用 DBMS_OUTPUT.PUT_LINE('获取到令牌:' || l_token); EXCEPTION WHEN OTHERS THEN IF UTL_HTTP.GET_RESPONSE_STATUS(l_res) IS NOT NULL THEN UTL_HTTP.END_RESPONSE(l_res); END IF; RAISE; END; /
2. 使用令牌调用目标API
拿到令牌后,每次请求时添加Authorization头部即可:
DECLARE l_req UTL_HTTP.REQ; l_res UTL_HTTP.RESP; l_token VARCHAR2(4000) := '你的令牌内容'; -- 可从存储表读取 l_buffer VARCHAR2(4000); BEGIN -- 初始化API请求 l_req := UTL_HTTP.BEGIN_REQUEST('https://目标API地址', 'GET'); -- 设置令牌认证头部 UTL_HTTP.SET_HEADER(l_req, 'Authorization', 'Bearer ' || l_token); -- 按需添加其他请求头部 UTL_HTTP.SET_HEADER(l_req, 'Content-Type', 'application/json'); -- 处理API响应 l_res := UTL_HTTP.GET_RESPONSE(l_req); WHILE UTL_HTTP.END_OF_RESPONSE(l_res) = FALSE LOOP UTL_HTTP.READ_TEXT(l_res, l_buffer, 4000); DBMS_OUTPUT.PUT_LINE('API响应内容:' || l_buffer); END LOOP; UTL_HTTP.END_RESPONSE(l_res); EXCEPTION WHEN OTHERS THEN IF UTL_HTTP.GET_RESPONSE_STATUS(l_res) IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE('请求失败,状态码:' || UTL_HTTP.GET_RESPONSE_STATUS(l_res)); UTL_HTTP.END_RESPONSE(l_res); END IF; RAISE; END; /
额外注意事项
- 需给数据库用户授予
UTL_HTTP执行权限:GRANT EXECUTE ON UTL_HTTP TO 你的用户名; - 若访问HTTPS接口,需配置Oracle Wallet(测试环境可临时禁用证书验证);
- 需配置网络ACL允许访问服务商域名:
BEGIN DBMS_NETWORK_ACL_ADMIN.CREATE_ACL( acl => 'rest_service_acl.xml', description => '授权访问REST服务', principal => '你的用户名', is_grant => TRUE, privilege => 'connect', start_date => SYSTIMESTAMP, end_date => NULL ); DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL( acl => 'rest_service_acl.xml', host => '服务商域名', lower_port => 443, upper_port => 443 ); COMMIT; END; /
内容的提问来源于stack exchange,提问作者user3436905
相关产品推荐
相关产品推荐

