C#/VB.NET调用OAuth接口获取认证Token返回无授权如何排查
问题背景
现有如下cURL命令,用于从指定URL接口获取认证Token:
$(curl 'https://api.api.api.com/api/auth/auth/oauth/token' -H 'accept: application/json, text/plain, */*' -H 'authorization: Basic KZZZOnRoaJJms3NlQ3JluO==' --data 'grant_type=password&scope=webclient&username=user1.user2&password=???????????'| jq -r '.access_token')
需要在ASP.NET(C#/VB.NET)中实现相同的Token获取效果,但自行编写的实现代码始终返回NO AUTHORIZATION(无授权)错误,原实现代码如下:
Private Sub AuthTOKEN() Try Dim consumerSecret As String = "KZZZOnRoaJJms3NlQ3JluO==" Dim accessToken As String Dim myURL As String = "https://api.api.api.com/api/auth/auth/oauth/token" Dim byte1 As Byte() = Encoding.ASCII.GetBytes("grant_type=password&scope=webclient&username=user1.user2&password=password") Dim bearerReq As HttpWebRequest = TryCast(WebRequest.Create(myURL), HttpWebRequest) bearerReq.Accept = "application/json, text/plain, */*" bearerReq.Method = "POST" bearerReq.ContentType = "application/x-www-form-urlencoded" bearerReq.ContentLength = byte1.Length bearerReq.KeepAlive = False bearerReq.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(Encoding.[Default].GetBytes(consumerSecret))) Dim newStream As Stream = bearerReq.GetRequestStream() newStream.Write(byte1, 0, byte1.Length) Dim bearerResp As WebResponse = bearerReq.GetResponse() Using reader = New StreamReader(bearerResp.GetResponseStream(), Encoding.UTF8) Dim response = reader.ReadToEnd() Dim bearer As Bearer = JsonConvert.DeserializeObject(Of Bearer)(response) accessToken = bearer.access_token End Using Console.WriteLine(accessToken) Console.Read() Catch ex As Exception MsgBox(ex.ToString) Finally End Try End Sub
错误根因
代码存在两个直接导致授权失败的问题:
- 对Authorization凭据做了二次Base64编码:定义的
consumerSecret变量值KZZZOnRoaJJms3NlQ3JluO==本身就是已经完成Base64编码的Basic认证凭据,和cURL请求头里的值完全一致。但代码中又调用Convert.ToBase64String()对该值做了一次编码,最终发送的Authorization头和cURL的有效值完全不符,服务端校验直接失败。 - 编码使用不规范:处理凭据字节时使用了
Encoding.Default,该编码随操作系统区域设置变化,存在和服务端预期编码不匹配的风险,标准HTTP头编码应使用ASCII或UTF8。
修正后代码
只需要调整Authorization头的赋值逻辑,替换错误的编码即可:
Private Sub AuthTOKEN() Try Dim consumerSecret As String = "KZZZOnRoaJJms3NlQ3JluO==" Dim accessToken As String Dim myURL As String = "https://api.api.api.com/api/auth/auth/oauth/token" ' 注意替换为实际的密码值 Dim formData As Byte() = Encoding.ASCII.GetBytes("grant_type=password&scope=webclient&username=user1.user2&password=你的实际密码") Dim bearerReq As HttpWebRequest = TryCast(WebRequest.Create(myURL), HttpWebRequest) bearerReq.Accept = "application/json, text/plain, */*" bearerReq.Method = "POST" bearerReq.ContentType = "application/x-www-form-urlencoded" bearerReq.ContentLength = formData.Length bearerReq.KeepAlive = False ' 直接拼接已编码好的凭据,不要二次Base64 bearerReq.Headers.Add("Authorization", "Basic " & consumerSecret) Using newStream As Stream = bearerReq.GetRequestStream() newStream.Write(formData, 0, formData.Length) End Using Dim bearerResp As WebResponse = bearerReq.GetResponse() Using reader = New StreamReader(bearerResp.GetResponseStream(), Encoding.UTF8) Dim response = reader.ReadToEnd() Dim bearer As Bearer = JsonConvert.DeserializeObject(Of Bearer)(response) accessToken = bearer.access_token End Using Console.WriteLine(accessToken) Console.Read() Catch ex As Exception MsgBox(ex.ToString) End Try End Sub
额外注意:原代码表单里的password值写的是明文
password占位符,需要替换为cURL中对应的实际密码,否则也会返回账号密码校验失败。
内容的提问来源于stack exchange,提问作者Franco
相关产品推荐
相关产品推荐

