使用 jersey 2 客户端刷新 OAuth 令牌

Refresh OAuth token with jersey 2 client

我目前正在将应用程序从 jersey 1 迁移到 2。在旧应用程序中,我们为所有自动刷新过期 OAuth 令牌的 jersey 客户端使用了 ClientFilter,如下所示:

@Override
public ClientResponse handle(ClientRequest cr) {
  ClientResponse resp = getNext().handle(cr);
  if (resp.getStatus() == Status.UNAUTHORIZED.getStatusCode()) {
    // Try to refresh the token
    boolean refreshed = refreshToken(oAuthInfo);
    if (refreshed) {
      resp = getNext().handle(cr);
    }
  }
  return resp;
}

这可能不是最优雅的方式,但好处是其余客户端用户不必自己关心过期的令牌。

有了球衣2的ContainerResponseFilter,这似乎不再那么简单了。我目前看到的唯一选择是使用 ClientRequestContext 并尝试使用 getClientgetHeaders 等重新创建原始请求...然后在 [=16= 中更新结果].然而,这似乎有点笨拙,所以我想知道是否有更方便的方法来刷新 OAuth 令牌,而无需在使用 jersey 客户端的任何地方处理这个问题?

看起来没有比使用客户端过滤器拦截响应、在需要时刷新令牌并尝试使用新令牌重复完全相同的请求更方便的方法了。其实jersey自己的filter也使用了这种做法classes.

可以在 jerseys HttpAuthenticationFilter:

中找到用于从过滤器 class 中重复原始 rest 调用的示例代码
static boolean repeatRequest(ClientRequestContext request, ClientResponseContext response, String newAuthorizationHeader) {
    Client client = request.getClient();

    String method = request.getMethod();
    MediaType mediaType = request.getMediaType();
    URI lUri = request.getUri();

    WebTarget resourceTarget = client.target(lUri);

    Invocation.Builder builder = resourceTarget.request(mediaType);

    MultivaluedMap<String, Object> newHeaders = new MultivaluedHashMap<String, Object>();

    for (Map.Entry<String, List<Object>> entry : request.getHeaders().entrySet()) {
        if (HttpHeaders.AUTHORIZATION.equals(entry.getKey())) {
            continue;
        }
        newHeaders.put(entry.getKey(), entry.getValue());
    }

    newHeaders.add(HttpHeaders.AUTHORIZATION, newAuthorizationHeader);
    builder.headers(newHeaders);

    builder.property(REQUEST_PROPERTY_FILTER_REUSED, "true");

    Invocation invocation;
    if (request.getEntity() == null) {
        invocation = builder.build(method);
    } else {
        invocation = builder.build(method,
                Entity.entity(request.getEntity(), request.getMediaType()));
    }
    Response nextResponse = invocation.invoke();

    if (nextResponse.hasEntity()) {
        response.setEntityStream(nextResponse.readEntity(InputStream.class));
    }
    MultivaluedMap<String, String> headers = response.getHeaders();
    headers.clear();
    headers.putAll(nextResponse.getStringHeaders());
    response.setStatus(nextResponse.getStatus());

    return response.getStatus() != Response.Status.UNAUTHORIZED.getStatusCode();
}

此代码用于 DigestAuthenticator or BasicAuthenticator 中的示例,以在从服务器收到 Unauthorised 响应的情况下使用提供的凭据重复请求。