在 Kotlin 中计算 oauth_signature 和 oauth_nonce
Calculating oauth_signature and oauth_nonce in Kotlin
我正在开发一个推特 android 应用程序,该应用程序具有 sign-in 推特功能。 Sign-in 效果很好。但我的问题是我想搜索用户。我用谷歌搜索并找到了端点。
https://api.twitter.com/1.1/users/search.json
然后我创建了一个改进功能来获取搜索用户:
@GET("users/search.json")
suspend fun searchUser(
@Header("authorization") header: String,
@Query("q") search: String
) : Response<List<InspectedUserPOJO>>
然后像这样从片段中调用它:
CoroutineScope(viewModelJob).launch {
withContext(IO) {
try {
val response = RetrofitInstance.retrofitInstance!!.searchUser(generateHeader(),"teyyihan")
if (response.isSuccessful) {
if (response.body() != null) {
// getting response
} else {
}
} else {} } catch (e: Exception) {}
}
}
这里是 generateHeader() 函数:
fun generateHeader(): String{
var header = "OAuth oauth_consumer_key=\""+/* my consumer key*/+"\",oauth_token=\""+CurrentUserInfo.authToken+"\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1580300189\",oauth_nonce=\"iBryT2SIbXa\",oauth_version=\"1.0\",oauth_signature=\"EvMhzhOKw%2BVhRKw5Iz%2F48VdWdlQ%3D\""
return header
}
实际上这个 header 来自邮递员。我测试了这个 header 并且效果很好。但是,每次我发送请求时,oauth_nonce 和 oauht_signature 都会发生变化。我试图用我的 oauht_token 更改 oauth_token 但它不起作用。那么我如何计算 oauth_nonce 和 oauth_signature?
另外我在 java 工作了 1 年如果你知道 java 方式请回答我。
一个可能的解决方案是让您添加 header 使用和拦截器,然后构建改造 object:
Interface YourService:{
//Your method
@GET("users/search.json")
suspend fun searchUser(
@Header("authorization") header: String,
@Query("q") search: String
) : Response<List<InspectedUserPOJO>>
companion object:{
fun createService(): YourService {
val headerAuthorizationInterceptor = Interceptor { chain ->
var request = chain.request()
val headers = request.headers().newBuilder().add("OAuth oauth_consumer_key", /*consumer key*/)
.add("Second Header", Second key)
.add("Content-Type", "application/json").build() //I am guessing content type is application/json
request = request.newBuilder().headers(headers).build()
chain.proceed(request)
}
val okHttpClient = OkHttpClient.Builder()
.readTimeout(20, TimeUnit.SECONDS)
.connectTimeout(20, TimeUnit.SECONDS)
.addInterceptor(headerAuthorizationInterceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl(Your base url)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(YourService::class.java)
}
}
}
完成此实施后,headerAuthorizationInterceptor 变量就是您添加 header 的变量。希望对你有帮助
我找到了一个解决方案,它使用改造,你不需要显式计算 oauth_nonce 或 oauth_signature。
首先你需要实现这些库:
implementation 'se.akerfeldt:okhttp-signpost:1.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.0.0-RC1'
implementation 'oauth.signpost:signpost-core:1.2.1.2'
implementation("com.squareup.okhttp3:logging-interceptor:4.3.1")
我们将有一个 class 名为 RetrofitClient:
class RetrofitClient {
companion object {
private var retrofit: Retrofit? = null
private val gSON = GsonBuilder()
.setLenient()
.create()
fun getClient(baseUrl: String, consumer: OkHttpOAuthConsumer): Retrofit? {
val logging = HttpLoggingInterceptor()
if (BuildConfig.DEBUG) {
logging.level = HttpLoggingInterceptor.Level.BODY
} else {
logging.level = HttpLoggingInterceptor.Level.NONE
}
val httpClient = OkHttpClient.Builder()
httpClient.connectTimeout(60000, TimeUnit.SECONDS)
httpClient.writeTimeout(120000, TimeUnit.SECONDS)
httpClient.readTimeout(120000, TimeUnit.SECONDS)
httpClient.retryOnConnectionFailure(true)
httpClient.addInterceptor(SigningInterceptor(consumer))
httpClient.addInterceptor { chain ->
val request = chain.request()
val requestBuilder = request.newBuilder()
val modifiedRequest = requestBuilder.build()
chain.proceed(modifiedRequest)
}
httpClient.addNetworkInterceptor(logging)
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gSON))
.client(httpClient.build())
.build()
}
return retrofit
}
}
}
最后在你的 Retrofit 界面中创建一个 companion object:
companion object {
fun getOauthAPIService(): RetrofitTwitterAPI? {
val consumer = OkHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
consumer.setTokenWithSecret(CurrentUserInfo.authToken, CurrentUserInfo.authTokenSecret)
return RetrofitClient.getClient(BASE_URL, consumer)?.create(YOUR_RETROFIT_INTERFACE::class.java)
}
}
因此您可以调用 YOUR_RETROFIT_INTERFACE.getOauthAPIService()
并进行 https 调用。
改造和所有这些代码将处理额外的 headers,如 oauht_nonce、oauth_signature 等
我正在开发一个推特 android 应用程序,该应用程序具有 sign-in 推特功能。 Sign-in 效果很好。但我的问题是我想搜索用户。我用谷歌搜索并找到了端点。
https://api.twitter.com/1.1/users/search.json
然后我创建了一个改进功能来获取搜索用户:
@GET("users/search.json")
suspend fun searchUser(
@Header("authorization") header: String,
@Query("q") search: String
) : Response<List<InspectedUserPOJO>>
然后像这样从片段中调用它:
CoroutineScope(viewModelJob).launch {
withContext(IO) {
try {
val response = RetrofitInstance.retrofitInstance!!.searchUser(generateHeader(),"teyyihan")
if (response.isSuccessful) {
if (response.body() != null) {
// getting response
} else {
}
} else {} } catch (e: Exception) {}
}
}
这里是 generateHeader() 函数:
fun generateHeader(): String{
var header = "OAuth oauth_consumer_key=\""+/* my consumer key*/+"\",oauth_token=\""+CurrentUserInfo.authToken+"\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1580300189\",oauth_nonce=\"iBryT2SIbXa\",oauth_version=\"1.0\",oauth_signature=\"EvMhzhOKw%2BVhRKw5Iz%2F48VdWdlQ%3D\""
return header
}
实际上这个 header 来自邮递员。我测试了这个 header 并且效果很好。但是,每次我发送请求时,oauth_nonce 和 oauht_signature 都会发生变化。我试图用我的 oauht_token 更改 oauth_token 但它不起作用。那么我如何计算 oauth_nonce 和 oauth_signature?
另外我在 java 工作了 1 年如果你知道 java 方式请回答我。
一个可能的解决方案是让您添加 header 使用和拦截器,然后构建改造 object:
Interface YourService:{
//Your method
@GET("users/search.json")
suspend fun searchUser(
@Header("authorization") header: String,
@Query("q") search: String
) : Response<List<InspectedUserPOJO>>
companion object:{
fun createService(): YourService {
val headerAuthorizationInterceptor = Interceptor { chain ->
var request = chain.request()
val headers = request.headers().newBuilder().add("OAuth oauth_consumer_key", /*consumer key*/)
.add("Second Header", Second key)
.add("Content-Type", "application/json").build() //I am guessing content type is application/json
request = request.newBuilder().headers(headers).build()
chain.proceed(request)
}
val okHttpClient = OkHttpClient.Builder()
.readTimeout(20, TimeUnit.SECONDS)
.connectTimeout(20, TimeUnit.SECONDS)
.addInterceptor(headerAuthorizationInterceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl(Your base url)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(YourService::class.java)
}
}
}
完成此实施后,headerAuthorizationInterceptor 变量就是您添加 header 的变量。希望对你有帮助
我找到了一个解决方案,它使用改造,你不需要显式计算 oauth_nonce 或 oauth_signature。
首先你需要实现这些库:
implementation 'se.akerfeldt:okhttp-signpost:1.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.0.0-RC1'
implementation 'oauth.signpost:signpost-core:1.2.1.2'
implementation("com.squareup.okhttp3:logging-interceptor:4.3.1")
我们将有一个 class 名为 RetrofitClient:
class RetrofitClient {
companion object {
private var retrofit: Retrofit? = null
private val gSON = GsonBuilder()
.setLenient()
.create()
fun getClient(baseUrl: String, consumer: OkHttpOAuthConsumer): Retrofit? {
val logging = HttpLoggingInterceptor()
if (BuildConfig.DEBUG) {
logging.level = HttpLoggingInterceptor.Level.BODY
} else {
logging.level = HttpLoggingInterceptor.Level.NONE
}
val httpClient = OkHttpClient.Builder()
httpClient.connectTimeout(60000, TimeUnit.SECONDS)
httpClient.writeTimeout(120000, TimeUnit.SECONDS)
httpClient.readTimeout(120000, TimeUnit.SECONDS)
httpClient.retryOnConnectionFailure(true)
httpClient.addInterceptor(SigningInterceptor(consumer))
httpClient.addInterceptor { chain ->
val request = chain.request()
val requestBuilder = request.newBuilder()
val modifiedRequest = requestBuilder.build()
chain.proceed(modifiedRequest)
}
httpClient.addNetworkInterceptor(logging)
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gSON))
.client(httpClient.build())
.build()
}
return retrofit
}
}
}
最后在你的 Retrofit 界面中创建一个 companion object:
companion object {
fun getOauthAPIService(): RetrofitTwitterAPI? {
val consumer = OkHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
consumer.setTokenWithSecret(CurrentUserInfo.authToken, CurrentUserInfo.authTokenSecret)
return RetrofitClient.getClient(BASE_URL, consumer)?.create(YOUR_RETROFIT_INTERFACE::class.java)
}
}
因此您可以调用 YOUR_RETROFIT_INTERFACE.getOauthAPIService()
并进行 https 调用。
改造和所有这些代码将处理额外的 headers,如 oauht_nonce、oauth_signature 等