Android 拦截刷新令牌GRPC的调用
我在我的项目中使用GRPC和proto,我有密钥和授权令牌来访问服务器API。 所以,我需要使用我的权限更新密钥。 我正在建设这样一个频道:Android 拦截刷新令牌GRPC的调用,android,kotlin,interceptor,grpc,Android,Kotlin,Interceptor,Grpc,我在我的项目中使用GRPC和proto,我有密钥和授权令牌来访问服务器API。 所以,我需要使用我的权限更新密钥。 我正在建设这样一个频道: OkHttpChannelBuilder.forAddress(host, port) .usePlaintext() .intercept(auth, logger) .build() 我的拦截器看起来像: class AuthClientInterceptor( private val pref
OkHttpChannelBuilder.forAddress(host, port)
.usePlaintext()
.intercept(auth, logger)
.build()
我的拦截器看起来像:
class AuthClientInterceptor(
private val prefs: Preferences,
private val keyApi: KeyApi) : ClientInterceptor {
companion object {
private const val ACCESS_TOKEN = "authorization"
}
override fun <ReqT : Any?, RespT : Any?> interceptCall(method: MethodDescriptor<ReqT, RespT>?,
callOptions: CallOptions?,
next: Channel): ClientCall<ReqT, RespT> {
val call = next.newCall(method, callOptions)
val callForwarding = object : ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(call) {
override fun checkedStart(responseListener: Listener<RespT>?, headers: Metadata) {
synchronized(this@AuthClientInterceptor) {
val keyCreated = prefs.getAccessKeyCreated()
val keyExpires = prefs.getAccessKeyExpires()
val currentTime = System.currentTimeMillis()
if (currentTime < keyCreated || currentTime > keyExpires) {
keyApi.issueNewKey(prefs.getAuthority())
.map { it.data }
.doOnSuccess { prefs.setAccessKey(it.token) }
.doOnSuccess { prefs.setAccessKeyCreated(it.createdDate) }
.doOnSuccess { prefs.setAccessKeyExpires(it.expiresDate) }
.blockingGet()
}
}
val keyData = Metadata.Key.of(ACCESS_TOKEN, Metadata.ASCII_STRING_MARSHALLER)
if (headers[keyData] == null) {
headers.put(keyData, "Bearer ${prefs.getAccessKey()}")
}
call.start(responseListener, headers)
}
}
return callForwarding
}
}
类AuthClientInterceptor(
private val prefs:首选项,
private val keyApi:keyApi):ClientInterceptor{
伴星{
private const val ACCESS_TOKEN=“授权”
}
重写调用(方法:MethodDescriptor?,
callOptions:callOptions?,
下一个:频道):ClientCall{
val call=next.newCall(方法,callOptions)
val callForwarding=object:ClientInterceptors.CheckedForwardingClientCall(调用){
重写有趣的checkedStart(responseListener:Listener?,标题:元数据){
同步的(this@AuthClientInterceptor) {
val keyCreated=prefs.getAccessKeyCreated()
val keyExpires=prefs.getAccessKeyExpires()
val currentTime=System.currentTimeMillis()
如果(currentTime但我没有找到解决方案,也没有找到任何关于使用gRPC实现此功能的有用信息。有人能帮我吗?如果你想这样做,我想你必须按照你描述的那样在应用程序级别处理它。这是因为gRPC不知道您的应用程序级令牌
您所指的身份验证器是什么?以下是您可以使用的完整客户端侦听器类
class Interceptor() : ClientInterceptor {
override fun <ReqT : Any?, RespT : Any?> interceptCall(method: MethodDescriptor<ReqT, RespT>?, callOptions: CallOptions?, next: Channel?): ClientCall<ReqT, RespT> {
return object : ClientCall<ReqT, RespT>() {
var listener: Listener<RespT>? = null
var metadata: Metadata? = null
var message: ReqT? = null
var request = 0
var call: ClientCall<ReqT, RespT>? = null
override fun start(responseListener: Listener<RespT>?, headers: Metadata?) {
this.listener = responseListener
this.metadata = headers
}
override fun sendMessage(message: ReqT) {
assert(this.message == null)
this.message = message
}
override fun request(numMessages: Int) {
request += numMessages
assert(this.message == null)
}
override fun isReady(): Boolean {
return false
}
override fun halfClose() {
startCall(object : ForwardingClientCallListener<RespT>() {
var delegate: Listener<RespT>? = null
override fun onReady() {
delegate = listener
super.onReady()
}
override fun delegate(): Listener<RespT> {
if (delegate == null) {
throw IllegalStateException()
}
return delegate!!
}
override fun onClose(status: Status?, trailers: Metadata?) {
if (delegate == null) {
super.onClose(status, trailers)
return
}
if (!needToRetry(status, trailers)) {
delegate = listener
super.onClose(status, trailers)
return
}
startCall(listener) // Only retry once
}
private fun needToRetry(status: Status?, trailers: Metadata?): Boolean {
if (status?.code?.toStatus() == UNAUTHENTICATED) {
Log.e("code", status?.code.toString())
return true
}
return false
}
})
}
private fun startCall(listener: Listener<RespT>?) {
call = next?.newCall(method, callOptions)
val headers = Metadata()
headers.merge(metadata)
call?.start(listener, headers)
assert(this.message != null)
call?.request(request)
call?.sendMessage(message)
call?.halfClose()
}
override fun cancel(message: String?, cause: Throwable?) {
if (call != null) {
call?.cancel(message, cause)
}
listener?.onClose(Status.CANCELLED.withDescription(message).withCause(cause), Metadata())
}
}
}
}
class拦截器():ClientInterceptor{
覆盖调用(方法:MethodDescriptor?,调用选项:callOptions?,下一步:通道?):ClientCall{
返回对象:ClientCall(){
变量侦听器:侦听器?=null
变量元数据:元数据?=null
var消息:需求?=null
var请求=0
变量调用:ClientCall?=null
覆盖有趣的开始(responseListener:Listener?,headers:Metadata?){
this.listener=responseListener
this.metadata=headers
}
覆盖发送消息(消息:ReqT){
断言(this.message==null)
this.message=消息
}
覆盖乐趣请求(numMessages:Int){
请求+=numMessages
断言(this.message==null)
}
override fun isReady():布尔值{
返回错误
}
覆盖半关闭(){
startCall(对象:ForwardingClientCallListener(){
变量委托:侦听器?=null
重写onReady(){
委托=侦听器
super.onReady()
}
重写有趣的委托():侦听器{
if(委托==null){
抛出非法状态异常()
}
返回代理!!
}
覆盖关闭(状态:status?,拖车:Metadata?){
if(委托==null){
super.onClose(状态、拖车)
返回
}
如果(!需要重试(状态,拖车)){
委托=侦听器
super.onClose(状态、拖车)
返回
}
startCall(侦听器)//只重试一次
}
private fun needToRetry(状态:状态?、预告片:元数据?):布尔值{
如果(状态?.code?.toStatus()==未经验证){
Log.e(“代码”,状态?.code.toString())
返回真值
}
返回错误
}
})
}
私人娱乐startCall(侦听器:侦听器?){
call=next?.newCall(方法,callOptions)
val headers=元数据()
headers.merge(元数据)
调用?.start(侦听器、标题)
断言(this.message!=null)
呼叫?请求(请求)
呼叫?.sendMessage(消息)
呼叫?.halfClose()
}
覆盖乐趣取消(消息:字符串?,原因:可丢弃?){
如果(调用!=null){
呼叫?.取消(消息、原因)
}