![](/img/trans.png)
[英]Android Google oAuth2 “/oauth2/v4/token” request show exception file not found
[英]Kotlin Android oauth2 token request only returning errors
我正在為當地慈善組織開發用戶應用程序,需要訪問他們的 API。 API來自野杏,這是進行令牌請求的文檔:
身份驗證令牌是從 Wild Apricot 的身份驗證服務獲得的,該服務位於https://oauth.wildapricot.org 。 此服務遵循 oAuth 2.0。
這是我需要實現的訪問選項:
-----------------為了使用 API 密鑰獲取訪問令牌,您必須發出以下請求:
POST /auth/token HTTP/1.1
主持人:oauth.wildapricot.org
授權:基本 BASE64_ENCODED("APIKEY:YOUR_API_KEY")
內容類型:application/x-www-form-urlencoded
grant_type=client_credentials&scope=auto
- - - - - - - - - - - - - - - -所以。 最后,您的請求將如下所示:
POST /auth/token HTTP/1.1
主持人:oauth.wildapricot.org
授權:基本 QVBJS0VZOm85c2U4N3Jnb2l5c29lcjk4MDcwOS0=
內容類型:application/x-www-form-urlencoded
grant_type=client_credentials&scope=auto
我正在嘗試使用 Retrofit2 和 okhttp3 攔截器進行此調用,並獲得了錯誤的請求響應(我非常陌生並且正在學習,除了 400 個錯誤的請求(當我使用“ /auth/token" 作為端點),或者找不到 404(當我使用“/auth/token HTTP/1.1”作為端點時)。如果有人能告訴我我到底在哪里搞砸了這將不勝感激,我試過的代碼如下。
界面:
interface WAApiCall {
@POST("auth/token")
fun callPost(@Body body:String ): Call<AuthToken>
}
呼叫服務:
object WAApiCallService {
private const val API_KEY = "xxxxxxxxIxHavexAxValidxKeyxxxx"
private const val BASE_URL = "https://oauth.wildapricot.org/"
private val AUTH = "Basic" + Base64.encodeToString(API_KEY.toByteArray(), Base64.NO_WRAP)
private const val CONTENT_TYPE = "application/x-www-form-urlencoded"
private var api:WAApiCall? = null
private fun getWAApi(context: Context) : WAApiCall {
if(api==null){
val OkHttpClient = OkHttpClient.Builder()
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BASIC
OkHttpClient.addInterceptor{chain ->
val request = chain.request()
Log.d("CALL", request.body.toString())
val newRequest = request.newBuilder()
.addHeader("Host", "oauth.wildapricot.org")
.addHeader("Authorization", AUTH )
.addHeader("Content-type", CONTENT_TYPE)
.method(request.method, request.body)
.build()
chain.proceed(newRequest)
}
api = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient.build())
.build()
.create(WAApiCall::class.java)
}
return api!!
}
fun call(context: Context) =
getWAApi(context)
}
Main Activity 中的函數進行調用:
fun testRequest(){
val call = WAApiCallService.call(this)
call.callPost("grant_type=client_credentials&scope=auto")
.enqueue(object: Callback<AuthToken>{
override fun onFailure(call: Call<AuthToken>, t: Throwable) {
Log.i("FAILURE", t.localizedMessage)
}
override fun onResponse(call: Call<AuthToken>, response: Response<AuthToken>) {
Log.i("SUCCESS", "TOKEN = ${response.body().toString()}")
Log.i("SUCCESS", "${response}")
val token = response.body()?.accessToken
Log.i("SUCCESS", "TOKEN = $token")
}
})
}
錯誤信息:
I/SUCCESS: TOKEN = null I/SUCCESS: Response{protocol=http/1.1, code=400, message=Bad Request, url=https://oauth.wildapricot.org/auth/token}
我想我只是不明白如何以某種基本方式實現這種類型的請求,我也無法讓它在 Postman 中工作。 我知道我需要將憑據發送到身份驗證服務器,並接收一個訪問令牌,該令牌將過期並需要刷新,並且它將包含在每個實際的 API 端點調用中,我想我只是錯過了一些東西在該過程中最重要的步驟中至關重要(獲得實際令牌,我想這是一個簡單的、拍打額頭的誤會?)。 Wild apricot API 位於 swagger hub 上,我可以使用我的 API 密鑰通過該 UI 訪問並查看響應,因此我知道它是有效的。
您的客戶端憑據請求看起來大部分都很好。 我能看到的唯一錯誤是 AUTH 標頭中“基本”和編碼憑據之間沒有空格字符。
如果這不起作用,您能否跟蹤 HTTP 請求並驗證您正在發送您認為的消息。
謝謝你的觀察,它讓我弄清楚了我最初的嘗試最終出了什么問題。 添加該空間后,我跟蹤請求,發現它實際上發送了兩個內容類型的標頭。
解決方法是在接口的改造調用中設置標頭:
interface WAApiCall {
@POST("auth/token")
fun callPost(@Body Body: okhttp3.RequestBody, @Header("Content-type") type: String): Call<AuthToken>
}
正如你所看到的 body 也略有不同,調用正在通過但正在返回:
“unsupported_grant_type”。
我傳遞了一個原始字符串作為 body 參數,它在請求中包含引號。 解決方案是在進行實際調用的函數中傳遞 okhttp3.Request 正文類型而不是原始字符串,如下所示:
val body: "grant_type=client_credentials&scope=auto&obtain_refresh_token=true"
val requestBody = RequestBody.create("text/plain".toMediaTypeOrNull(),body)
val call = WAApiCallService.call(this)
call.callPost(requestBody,"application/x-www-form-urlencoded")
.enqueue(object: Callback<AuthToken>{
通過這些更改,呼叫成功了,我長期的頭痛也結束了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.