是否在oauth上缓存访问令牌



我目前正在谷歌上使用oauth2实现身份验证。

我已经读到我应该缓存访问令牌以备以后使用,但我真的需要这样做吗?

我考虑过在会话中加密存储它。如果它过期,我会得到一个新的令牌。

此外,如果我需要缓存令牌,我如何知道它属于哪个用户?

我已经读到我应该缓存访问令牌以备以后使用,但我真的需要这么做吗?

是的,这就是OAuth的用途。访问令牌用于让您的应用程序访问服务提供商的资源,而无需每次提供用户名和密码。

我考虑过在会话中加密存储它。如果过期,我将获得一个新的令牌。

看起来你把这里的事情搞混了。会话的到期和访问令牌的到期是不同的。访问令牌的使用寿命通常比会话长得多(例如,令牌:60分钟,会话:15分钟)。

如果访问令牌过期,则需要刷新令牌来获取新的访问令牌。如果您没有刷新令牌,则必须再次启动授权流以获得新的访问令牌。

此外,如果我需要缓存令牌,我如何知道它指向哪个用户归属?

您有责任在数据库中的某个地方维护该连接。服务提供商(在你的例子中是谷歌)在他们的一端也做同样的事情,以便将访问令牌与用户/资源相匹配。关于您的第二点:您还应该存储刷新令牌。


我建议你读过这里:为什么OAuth被设计为具有请求令牌和访问令牌?

您肯定应该缓存您的访问令牌。生成访问令牌的成本很高,而且通常它们的到期时间相对较长,因此可以多次重用,避免每次都有新的请求轰炸身份验证服务器。

举个例子,这里有一个非常简单的Scala缓存实现。实现oauth操作(getToken、refreshToken等)的类

class authHandler private(serviceURL: java.net.URL) {
  def getToken(clientId: String,
               clientSecret: String,
               scope: String,
               resource: String = ""): Future[String] = {
    val cacheKey = clientId + scope
    S2SAuthHandler.getTokenFromCache(cacheKey) match {
      case Some(tk) => Future(tk)
      case None => requestTokenFromServer(clientId, clientSecret, scope, resource)
    }
  }
  private def requestTokenFromServer(clientId: String,
                                     clientSecret: String,
                                     scope: String,
                                     resource: String): Future[String] = {
        val authToken = <http request from server>
//expiration time is set to a few seconds less than the one provided from the server, to avoid returning an already expired token. 
        authToken.expires = authToken.expires - 5 + System.currentTimeMillis() / 1000  S2SAuthHandler.storeTokenToCache(clientId + scope, authToken)

    authToken.accessToken      
    }
}

以及实现高速缓存的伴随对象。Scala中的配套对象是静态的,因此您可以创建尽可能多的oauth处理程序类实例,但仍有一个全局缓存可用。

缓存是一个简单的映射[key,token],其中的key可以是"clientId+作用域"。您希望为每个客户端和作用域存储不同的令牌。令牌应包含访问令牌本身,加上刷新令牌(如果可用)、过期时间等。

/** Companion objec  */
object authHandler {
  private val tokenCache = mutable.Map.empty[String, AuthToken]
  private def getTokenFromCache(cacheKey: String): Option[String] = {
    if ((tokenCache contains cacheKey) && (tokenCache(cacheKey).expires > System.currentTimeMillis / 1000)) {
      Some(tokenCache(cacheKey).accessToken)
    }
    else {
      None
    }
  }
  private def storeTokenToCache(key: String, tk: AuthToken) = {
    tokenCache(key) = tk
//Depending on your execution environment, I would recommend to encrypt the token before storing in the cache
   }
}

最新更新