Delphi RESTClient调用Azure公共RESTServer的OAuth2参数及超时问题排查
问题排查与解决方案
1. 优先解决网络超时问题(错误码12002)
- 你提到ping Azure VM公网IP超时但能正常获取OAuth2令牌,说明Azure VM的入站安全规则未开放REST服务使用的8080端口(令牌请求走Azure AD的443端口,所以不受影响)。
- 操作步骤:
- 登录Azure门户,找到目标VM的网络安全组(NSG)
- 添加入站规则:允许TCP协议、端口8080(或你计划使用的HTTPS端口443)、来源设为"任意"或指定客户端IP范围
- 注意:如果改用HTTPS,需确保VM上配置了有效的SSL证书,或通过Azure Application Gateway做SSL终止
2. 修正REST请求参数的错误配置
(1)GET请求不能使用pkREQUESTBODY参数
GET协议规范中没有请求体,本地测试正常是因为DataSnap对参数处理较宽松,但公网环境下会导致请求异常。
- 若接口设计为GET,将参数类型改为
pkURLQUERY:RESTRequest1.Params.AddItem('MyKey1', 'MyValue1', TRESTRequestParameterKind.pkURLQUERY); RESTRequest1.Params.AddItem('MyKey2', 'MyValue2', TRESTRequestParameterKind.pkURLQUERY); - 若接口原本是POST(本地调用时用POST),则将
RESTRequest1.Method改为rmPOST,保留pkREQUESTBODY参数
(2)正确设置Authorization请求头
直接用Params.AddItem添加Authorization会被当作URL参数或请求体参数,而非HTTP头,需明确指定为Header类型:
RESTRequest1.Params.AddHeader('Authorization', 'Bearer ' + FConnection.AuthToken);
3. Azure OAuth2 Scope配置与Delphi组件设置
- Azure端配置:
- 在Azure AD的应用注册中,找到你的REST Server对应的API应用,添加自定义Scope(比如
access_as_user) - 在Client应用的API权限中,添加上述Scope并授予管理员同意
- 在Azure AD的应用注册中,找到你的REST Server对应的API应用,添加自定义Scope(比如
- Delphi端设置:
在TOAuth2Authenticator组件中指定Scope属性,确保请求令牌时包含该权限:OAuth2Authenticator5.Scope := 'api://<你的API应用ID>/access_as_user'; - 验证令牌:用JWT解析工具(比如jwt.ms)获取到的
access_token,检查scp字段是否包含配置的Scope,aud字段是否匹配你的API应用ID,不匹配的话API会拒绝访问
4. 修正后的调用代码示例
procedure MyForm.Button1Click(Sender: TObject); var RESTClient1: TRESTClient; RESTRequest1: TRESTRequest; strImageJSON : string; begin // 建议用HTTPS,需确保VM配置了SSL证书或通过网关转发 RESTClient1 := TRESTClient.Create('https://<Azure Public IP>:443/'); try RESTRequest1 := TRESTRequest.Create(nil); try // 根据接口实际设计选择Method,这里假设是POST RESTRequest1.Method := TRESTRequestMethod.rmPOST; RESTRequest1.Resource := 'api/<MyAzureResource>'; // 不需要在Resource里加ClientID,除非你的API路由设计如此 // POST请求用RequestBody参数 RESTRequest1.Params.AddItem('MyKey1', 'MyValue1', TRESTRequestParameterKind.pkREQUESTBODY); RESTRequest1.Params.AddItem('MyKey2', 'MyValue2', TRESTRequestParameterKind.pkREQUESTBODY); // 正确添加Authorization头 RESTRequest1.Params.AddHeader('Authorization','Bearer ' + FConnection.AuthToken); RESTRequest1.Client := RESTClient1; // 可以设置超时时间,避免默认过短 RESTRequest1.Timeout := 30000; RESTRequest1.Execute; strImageJSON := RESTRequest1.Response.Content; finally RESTRequest1.Free; end; finally RESTClient1.Free; end; end;
内容的提问来源于stack exchange,提问作者Mike V
相关产品推荐
相关产品推荐

