如何在VB.NET遗留代码库中集成UPS OAuth 2.0认证
VB.NET遗留系统集成UPS OAuth 2.0认证方案
核心变更说明
UPS OAuth2.0认证不再使用原有的UsernameToken(用户名+密码),而是需要先通过客户端凭证模式获取Access Token,再将Token以Bearer {Token}的形式添加到请求头中,同时保留原有的ServiceAccessToken(AccessLicenseNumber)配置。
1. 实现Access Token获取逻辑
编写获取UPS OAuth Token的VB.NET方法,注意区分测试与生产环境端点:
Imports System.Net Imports System.Text Public Function GetUpsOAuthToken() As String ' 替换为你的UPS OAuth凭证 Dim clientId As String = CarrierConnection.ClientId ' UPS开发者平台创建的Client ID Dim clientSecret As String = CarrierConnection.ClientSecret ' 对应的Client Secret Dim accessLicenseNumber As String = CarrierConnection.AccessLicenseNumber ' 原有的AccessLicenseNumber ' 测试环境端点:https://wwwcie.ups.com/security/v1/oauth/token ' 生产环境端点:https://onlinetools.ups.com/security/v1/oauth/token Dim tokenEndpoint As String = "https://wwwcie.ups.com/security/v1/oauth/token" Dim request As HttpWebRequest = CType(WebRequest.Create(tokenEndpoint), HttpWebRequest) request.Method = "POST" request.ContentType = "application/x-www-form-urlencoded" request.Headers.Add("x-merchant-id", accessLicenseNumber) ' 构造请求体 Dim postData As String = $"grant_type=client_credentials&client_id={Uri.EscapeDataString(clientId)}&client_secret={Uri.EscapeDataString(clientSecret)}" Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData) request.ContentLength = byteArray.Length ' 写入请求体 Using dataStream As Stream = request.GetRequestStream() dataStream.Write(byteArray, 0, byteArray.Length) End Using ' 获取响应并解析Token Using response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse) Using reader As New StreamReader(response.GetResponseStream()) Dim responseJson As String = reader.ReadToEnd() ' 用Newtonsoft.Json解析JSON,提取access_token字段 Dim tokenObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(responseJson) Return tokenObj("access_token").ToString() End Using End Using End Function
2. 修改原有UPS服务客户端的认证逻辑
替换原有的UsernameToken配置,改为添加OAuth Authorization请求头:
' 保留原有的ServiceAccessToken配置 Dim upss As New UPSSecurity() Dim upssSvcAccessToken As New UPSSecurityServiceAccessToken() upssSvcAccessToken.AccessLicenseNumber = CarrierConnection.AccessLicenseNumber upss.ServiceAccessToken = upssSvcAccessToken ' 不再设置UsernameToken,改为获取OAuth Token并添加到请求头 Dim oauthToken As String = GetUpsOAuthToken() ' 初始化ShipPortTypeClient Dim shpSvc As New ShipPortTypeClient(ShipPortTypeClient.EndpointConfiguration.ShipPort, CarrierConnection.url) ' 清空原有认证信息,添加OAuth头 shpSvc.ClientCredentials.HttpDigest.ClientCredential.UserName = "" shpSvc.ClientCredentials.HttpDigest.ClientCredential.Password = "" Dim authHeader As New System.ServiceModel.Channels.MessageHeader(Of String)($"Bearer {oauthToken}") Dim untypedHeader As System.ServiceModel.Channels.MessageHeader = authHeader.GetUntypedHeader("Authorization", "") shpSvc.ChannelFactory.Endpoint.Behaviors.Add(New CustomHeaderBehavior(untypedHeader))
3. 自定义WCF行为类(注入请求头)
创建自定义行为类,确保OAuth头被添加到每个请求中:
Imports System.ServiceModel.Description Imports System.ServiceModel.Channels Imports System.ServiceModel.Dispatcher Public Class CustomHeaderBehavior Implements IEndpointBehavior Private ReadOnly _header As MessageHeader Public Sub New(header As MessageHeader) _header = header End Sub Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters ' 无需处理 End Sub Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior clientRuntime.ClientMessageInspectors.Add(New CustomHeaderInspector(_header)) End Sub Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior ' 无需处理 End Sub Public Sub Validate(endpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate ' 无需处理 End Sub End Class Public Class CustomHeaderInspector Implements IClientMessageInspector Private ReadOnly _header As MessageHeader Public Sub New(header As MessageHeader) _header = header End Sub Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply ' 无需处理 End Sub Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest request.Headers.Add(_header) Return Nothing End Function End Class
关键注意事项
- Token缓存:UPS OAuth Token有效期为1小时,建议将获取到的Token缓存,避免重复请求Token端点,提升性能。
- 环境区分:测试与生产环境的Token端点、服务地址不同,需根据部署环境切换。
- 依赖库:确保项目引用Newtonsoft.Json(.NET Framework环境推荐)或System.Text.Json用于解析JSON响应。
- 权限验证:确认UPS Client ID和Client Secret拥有对应服务(如Ship)的调用权限。
内容的提问来源于stack exchange,提问作者Rakib Ahmed
相关产品推荐
相关产品推荐

