首页 > 解决方案 > Oauth2.0中如何使用refresh_token重新生成access_token

问题描述

我们使用 Spring Cloud Netflix Zull 作为后端服务的网关应用程序。前端是 Angular。但我们仅在 Postman 中测试端点(前端正在开发中)。我们有一个名为的模块LoginServiceModule,另一个是ZullServerModule. LoginSericeModuke从前端获取用户名和密码,并通过包含所需的标头和正文来调用以下 oauth/token 端点。

 http://localhost:XXXX/login

响应是

{
    "access_token": "XXXXXXXXX",
    "token_type": "bearer",
    "refresh_token": "XXXXXXXXX",
    "expires_in": 3600,
    "scope": "read write",
    "jti": "XXXXXXXXXXX"
}

ZullServerModule包含ZullServerConfiguration、授权服务器配置和资源服务器配置等...

内部调用像这样的LoginModuleoauth/token 端点。

ResponseEntity<String> loginResponse =  restTemplate.exchange("http://localhost:XXXX/oauth/token", HttpMethod.POST, entity, String.class);

反应是..

{
    "access_token": "XXXXXXXXX",
    "token_type": "bearer",
    "refresh_token": "XXXXXXXXX",
    "expires_in": 3600,
    "scope": "read write",
    "jti": "XXXXXXXXXXX"
}

我们从响应中提取 access_token 并调用以下端点...

http://localhost:XXXX/ProjectName/api/endpointname?access_token={access_token}.

但是当 access_token 过期时,当我访问上面的后端服务 url 时,它的说法

{
    "error": "invalid_token",
    "error_description": "Access token expired:XXXXXXXXXXXXXXX(access_token)"
}

我知道它已过期并尝试在这样的终端中借助 refresh_token 重新生成 access_token

curl clientID:clientSecret@localhost:XXXX/oauth/token -d grant_type=refresh_token -drefresh_token={refresh_token}

但我需要将其包含在我们的代码中,并且不知道将其放置在哪里。在网上搜索后,我遇到了ZullFilter。我尝试了所有前置、路由和后置过滤器。对于每个请求,它们都被执行(即只要 access_token 未过期),但是当令牌过期并且如果我测试端点时,没有任何过滤器被执行并且我得到错误响应

{
    "error": "invalid_token",
    "error_description": "Access token expired: XXXXXXXXXX"
}

我已将 sysouts 置于每个过滤器的运行方法中。我对 filterOrder 也不太了解。

@Override
public Object run() throws ZuulException {
    System.out.println("pre filter...");
    RequestContext context = 
    RequestContext.getCurrentContext();
    HttpServletResponse response = context.getResponse();
    System.out.println(response.getStatus());
    return null;
}

我想在 refresh_token 的帮助下控制 access_token 的生成。每当 access_token 过期时,我如何编码,如果我在过期后访问资源,那么我会知道令牌过期并重新生成 access_token 并使用新的 access_token 调用先前的调用。

标签: javaspring-bootoauth-2.0spring-cloud-netflix

解决方案


通常,客户端负责维护自己的令牌并在令牌即将到期时对其进行刷新。将此逻辑移动到 Zuul 层似乎是一个非常糟糕的主意。考虑一下实现,它将如何工作?

一旦客户端的令牌过期,它将使用永久过期的令牌调用您的端点,Zuul 必须尝试在每个请求中刷新。这会为每个 API 调用增加很多开销。您可能会引入某种黑客攻击,您总是在响应标头或其他东西中传回新令牌......但此时您将违反OAuth2 的授权流程


推荐阅读