当前位置: 首页 > 知识库问答 >
问题:

我需要获取auth令牌并将其设置在头中

茅涵映
2023-03-14

我是Spring启动和反应式编程的新手。

我正在为外部api服务使用Spring webflow webclient。我需要获取auth令牌并将其设置在标头中

WebClient.builder()
            .baseUrl(baseUrl)
            .filter((request, next) -> {
                return next.exchange(request)
                        .flatMap((Function<ClientResponse, Mono<ClientResponse>>) clientResponse -> {
                            if (clientResponse.statusCode().value() == 401) {
                                return authenticate().map(token -> {
                                    Token accessToken = authenticate().block();
                                    ClientRequest retryRequest = ClientRequest.from(request).header("Authorisation", "Bearer " + accessToken.getAccessToken()).build();
                                    return next.exchange(retryRequest);
                                }).
                            } else {
                                return Mono.just(clientResponse);
                            }
                        });
            })
            .defaultHeader("Authorization", "Bearer " + authToken.getAccessToken())
            .build();


private Mono<Token> authenticate() {
    MultiValueMap<String, String> params = new LinkedMultiValueMap();
    params.add("client_id", clientId);
    params.add("client_secret", clientSecret);
    params.add("grant_type", "password");
    params.add("username", username);
    params.add("password", password);

    WebClient client = WebClient.create(baseUrl);
    return client
            .post()
            .uri(tokenUri)
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .syncBody(params)
            .retrieve()
            .bodyToMono(Token.class);
}

private static class Token {
    @JsonProperty("access_token")
    private String accessToken;

    public String getAccessToken() { return accessToken; }
}

在应用程序启动期间,我将获取访问令牌并在 Web 客户端生成器中进行设置。我创建了一个过滤器来处理令牌到期后的身份验证失败。但是上面的代码会抛出错误,因为我使用了block(),它不应该在Reactor线程中使用。我还能如何处理它?我正在使用 oauth2 资源所有者密码授予流。有没有其他方法来处理流量?

共有2个答案

仲承福
2023-03-14

我知道这是一个旧线程,但我找不到任何其他适用于初始问题的示例

基本上,我无法从上面的示例中编写工作代码……主要任务是:通过提供Bearer令牌,使用WebClient实例获取受保护的资源。可通过单独的请求请求不记名令牌。

Mono authenticate()应该可以很好地获得新的令牌。

        WebClient client2 =  WebClient.builder()
                                    .baseUrl(SERVER_URL)
                                    .filter((request, next) -> {
                                        return next.exchange(request)
                                                .flatMap( clientResponse -> {
                                                    if (clientResponse.statusCode().value() == 401) {
                                                        return authenticate().map(token -> {
                                    Token accessToken = authenticate().block();
                                    ClientRequest retryRequest = ClientRequest.from(request).header("Authorisation", "Bearer " + accessToken.getAccessToken()).build();
                                    return next.exchange(retryRequest);
                                });
                                                    } else {
                                                        return Mono.just(clientResponse);
                                                    }
                                                });
                                    })
                                    .defaultHeader("Authorization", "Bearer " + token.getAccessToken())
                                    .build();

对于上面的示例,无法将“. block()”替换为平面地图()

第二个例子

        WebClient client3 =  WebClient.builder().baseUrl("http://localhost:8080")
                                 //sets the header before the exchange
                                .filter(((request, next) -> tokenProvider.getAccessToken()
                                                    .map(setBearerTokenInHeader(request))
                                                    .flatMap(next::exchange)))
                
                                //do the exchange
                                .filter((request, next) -> next.exchange(request)
                                        .flatMap(clientResponse -> {
                                            if (clientResponse.statusCode().value() == 401) {
                                              //If unauthenicated try again 
                                                return authenticate()
                                                        .flatMap(Token::getAccessToken)
                                                        .map(setBearerTokenInHeader(request))
                                                        .flatMap(next::exchange);
                                            } else {
                                                return Mono.just(clientResponse);
                                            }
                                        }))
                                .build();

不确定什么是“令牌提供程序.get访问令牌()”和“.flatMap(令牌::获取访问令牌)”将不接受 由于

    class Token {
        String token = "";
        
        public String getAccessToken() { return token; }
    }

对不起,我是新手。如果您有一个工作示例,请在此线程中分享

刁璞
2023-03-14

嗨,我遇到了同样的问题(添加重试WebClient的所有请求),看起来你已经重用了。但这里的平面图是你的朋友,如果你有一个单声道

builder.baseUrl("http://localhost:8080")
             //sets the header before the exchange
            .filter(((request, next) -> tokenProvider.getAccessToken()
                                .map(setBearerTokenInHeader(request))
                                .flatMap(next::exchange)))
            //do the exchange
            .filter((request, next) -> next.exchange(request)
                    .flatMap(clientResponse -> {
                        if (clientResponse.statusCode().value() == 401) {
                          //If unauthenicated try again 
                            return authenticate()
                                    .flatMap(Token::getAccessToken)
                                    .map(setBearerTokenInHeader(request))
                                    .flatMap(next::exchange);
                        } else {
                            return Mono.just(clientResponse);
                        }
                    }))
            .build();

private Function<String, ClientRequest> setBearerTokenInHeader(ClientRequest request) {
        return token -> ClientRequest.from(request).header("Bearer ", token).build();
    }

 类似资料:
  • 我使用curl命令调用我的REST服务 我试图使用Python的请求库映射相同的代码 我的问题是,如何在代码中设置我的TOKEN值?

  • 尝试使用Google API的REST调用创建自动化的blogger post(不通过JavaScript或任何其他编码语言)。我能够使用api键和Auth2.0客户端创建所有的谷歌。https://console.cloud.google.com/apis/credentials APi和auth2由于get调用Blogger使用API Key,我可以进行所有的GET活动 为了使用API发布博客

  • 问题内容: 我正在尝试向每个API调用添加带有访问令牌的标头。它适用于所有GET请求,但是一旦我尝试进行POST,便不会添加标头。 这是我添加令牌的方法: 从这里调用: 我尝试这样做如下: 但这也不起作用。它仅在我如下更改标题键名称时才有效: 如何在AngularJs中为帖子分配默认标题并获取请求? 问题答案: 与其将令牌放在每个服务(或调用)内部的标头上,不如使用拦截器(docs在此处)。 然后

  • 我使用 Laravel Tymon/JWT-AUTH 进行 JWT 身份验证。但是当我进行身份验证时,只需获取访问令牌,而不是刷新令牌 in package.json 我希望得到一个刷新令牌来刷新令牌到期后,在配置/jwt.php我可以设置访问令牌和刷新令牌的到期时间,但我不能得到它。如何获得刷新令牌?

  • 我想从Stormpath帖子中对JWT令牌和CSRF提出疑问,这些令牌和CSRF解释了将JWT存储在localStorage或Cookie中的优缺点。 [...] 如果您使用JS从cookie中读取值,这意味着您不能在cookie上设置Httponly标志,因此现在站点上的任何JS都可以读取它,从而使其与在localStorage中存储内容的安全级别完全相同。 我试图理解为什么他们建议将xsrfT

  • 我的方法正确吗?在正文中发送凭据>接收响应(成功)>登录成功>将令牌存储在会话存储中并将其设置在头中>会话过期时注销 存储jwt