![](/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.