如何在T-SQL中维护HTTP会话以调用无Token认证的API
问题描述
我正在使用T-SQL调用API获取数据。需说明的是,这种方式并不理想,但由于无法修改代码库,只能在数据库端实现(内部网络环境,非公开)。
我通过以下脚本成功获取到API返回的“Login successful”响应,但该API不使用Token进行认证,因此无法在后续请求中通过Header传递Token。
DECLARE @AUTH_URL NVARCHAR(MAX) = '_api_url_login_'; Declare @Object as Int; Declare @Status as Int; Declare @ResponseText as Varchar(8000); Exec sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT; Exec sp_OAMethod @Object, 'open', NULL, 'post', @AUTH_URL, 'false' Exec sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded' Exec sp_OAMethod @Object, 'send', NULL, '{"username":"___", "password":"___"}' Exec sp_OAGetProperty @Object, 'status', @Status OUT Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT
直接在Chrome和Postman中登录并调用API可正常工作,但在SQL Server中无法成功,我认为原因是SQL Server不维护HTTP会话状态。
以下是我的GET请求代码,目前收到API返回的通用错误(无法提供具体错误信息):
DECLARE @JOB_URL NVARCHAR(MAX) = '_api_url_'; Declare @Object2 as Int; Declare @Status2 as Int; Declare @ResponseText2 as Varchar(8000); Exec sp_OACreate 'MSXML2.XMLHTTP', @Object2 OUT; Exec sp_OAMethod @Object2, 'open', NULL, 'get', @JOB_URL, 'False' Exec sp_OAMethod @Object2, 'send' Exec sp_OAGetProperty @Object2, 'status', @Status2 OUT Exec sp_OAMethod @Object2, 'responseText', @ResponseText2 OUTPUT select @ResponseText2 select @Status2
请问如何在T-SQL中将这两个请求发送到同一个HTTP会话中?
解决方案
要在T-SQL中维持同一个HTTP会话,核心是复用同一个MSXML2.ServerXMLHTTP对象,并确保会话Cookie被自动携带。浏览器和Postman会自动维护会话Cookie,但T-SQL中每次创建新对象都会开启新会话,具体调整步骤如下:
- 复用单一HTTP对象:不要创建两个独立的对象实例,登录请求完成后,继续使用同一个对象发送后续的GET请求。
- 依赖自动Cookie处理:
MSXML2.ServerXMLHTTP默认会自动保存登录请求返回的会话Cookie,复用对象时后续请求会自动携带该Cookie,从而维持会话。
调整后的完整脚本
DECLARE @AUTH_URL NVARCHAR(MAX) = '_api_url_login_'; DECLARE @JOB_URL NVARCHAR(MAX) = '_api_url_'; -- 仅创建一次HTTP对象,用于所有会话内请求 Declare @HttpObject as Int; Declare @Status as Int; Declare @ResponseText as Varchar(8000); -- 执行登录请求 Exec sp_OACreate 'MSXML2.ServerXMLHTTP', @HttpObject OUT; Exec sp_OAMethod @HttpObject, 'open', NULL, 'post', @AUTH_URL, 'false' Exec sp_OAMethod @HttpObject, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded' Exec sp_OAMethod @HttpObject, 'send', NULL, '{"username":"___", "password":"___"}' Exec sp_OAGetProperty @HttpObject, 'status', @Status OUT Exec sp_OAMethod @HttpObject, 'responseText', @ResponseText OUTPUT -- 验证登录结果 SELECT '登录响应内容: ' + @ResponseText, '登录状态码: ' + CAST(@Status AS VARCHAR(10)) -- 复用同一个对象发送GET请求 Exec sp_OAMethod @HttpObject, 'open', NULL, 'get', @JOB_URL, 'False' Exec sp_OAMethod @HttpObject, 'send' Exec sp_OAGetProperty @HttpObject, 'status', @Status OUT Exec sp_OAMethod @HttpObject, 'responseText', @ResponseText OUTPUT -- 获取GET请求结果 SELECT 'GET请求响应内容: ' + @ResponseText, 'GET请求状态码: ' + CAST(@Status AS VARCHAR(10)) -- 最后释放HTTP对象 Exec sp_OADestroy @HttpObject;
额外验证与注意事项
- 检查Cookie是否正确获取:可以在登录后添加代码提取返回的Cookie,确认会话标识已被保存:
Declare @SessionCookie as Varchar(8000); Exec sp_OAMethod @HttpObject, 'getResponseHeader', @SessionCookie OUT, 'Set-Cookie' SELECT '登录返回的会话Cookie: ' + @SessionCookie - 优先使用ServerXMLHTTP:避免使用
MSXML2.XMLHTTP,它是客户端组件,MSXML2.ServerXMLHTTP更适配SQL Server的服务器端环境,会话处理更稳定。 - 无需手动设置Cookie:只要复用同一个对象,组件会自动处理Cookie的存储和发送,除非API有特殊的Cookie规则需要手动干预。
内容的提问来源于stack exchange,提问作者Hyper10n
相关产品推荐
相关产品推荐

