You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Boost.Beast实现Google Drive OAuth2设备流遇307重定向求助

解决Boost.Beast请求Google OAuth2设备流返回307重定向的问题

嘿,我之前也踩过这个坑!这个307临时重定向的问题其实很好解决——Google的OAuth2设备流接口强制要求使用HTTPS访问,而你当前的Boost.Beast代码是通过普通HTTP发送请求的,所以服务器才会把你重定向到HTTPS版本的地址。Postman默认会自动用HTTPS访问这类接口,所以它能正常拿到JSON响应。

核心问题分析

你看到的307响应里的Location字段已经给出了明确提示:它指向的是https://accounts.google.com/o/oauth2/device/code,也就是HTTPS协议的地址。你的原始代码应该是连接到了HTTP的80端口,而Google的服务器会把所有HTTP请求重定向到HTTPS的443端口。

修改后的Boost.Beast HTTPS请求代码

要解决这个问题,你需要切换到Boost.Beast的HTTPS客户端实现,用ssl::stream包装TCP流来处理SSL握手。下面是完整的示例代码:

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <iostream>
#include <string>

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
namespace ssl = net::ssl;
using tcp = net::ip::tcp;

int main() {
    try {
        // 初始化IO上下文
        net::io_context ioc;

        // 创建SSL上下文,使用TLS 1.2版本
        ssl::context ctx(ssl::context::tlsv12_client);
        // 设置默认的CA证书路径(需要系统或OpenSSL的CA证书支持)
        ctx.set_default_verify_paths();

        // 创建带SSL的TCP流
        beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);

        // 设置服务器主机名验证,防止中间人攻击
        if(! SSL_set_tlsext_host_name(stream.native_handle(), "accounts.google.com")) {
            beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
            throw beast::system_error{ec};
        }

        // 解析服务器地址(端口443是HTTPS的默认端口)
        tcp::resolver resolver(ioc);
        auto const results = resolver.resolve("accounts.google.com", "443");

        // 连接到服务器的TCP端口
        beast::get_lowest_layer(stream).connect(results);
        // 执行SSL握手,建立HTTPS连接
        stream.handshake(ssl::stream_base::client);

        // 构造请求(内容和你之前的一致)
        http::request<http::string_body> req{http::verb::post, "/o/oauth2/device/code", 11};
        req.set(http::field::host, "accounts.google.com");
        req.set("Cache-Control", "no-cache");
        req.set(http::field::content_type, "application/x-www-form-urlencoded");
        req.body() = "scope=https://www.googleapis.com/auth/drive.file&client_id=610490019085-l1v2mv7lv95lu7cr111vbtqmp1bigv42.apps.googleusercontent.com";
        req.prepare_payload();

        // 发送HTTPS请求
        http::write(stream, req);

        // 接收服务器响应
        beast::flat_buffer buffer;
        http::response<http::dynamic_body> res;
        http::read(stream, buffer, res);

        // 打印响应内容
        std::cout << res << std::endl;

        // 关闭SSL流(忽略"未连接"的错误,因为可能服务器已经关闭连接)
        beast::error_code ec;
        stream.shutdown(ec);
        if(ec && ec != beast::errc::not_connected)
            throw beast::system_error{ec};
    } catch(std::exception const& e) {
        std::cerr << "请求出错: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

额外注意事项

  1. 链接依赖库:编译时需要链接Boost的system、beast、asio库,以及OpenSSL的ssl和crypto库。
  2. 证书验证:如果你的环境中找不到默认CA证书,可能需要手动指定证书路径,或者在测试环境临时禁用验证(生产环境绝对不能这么做,会有安全风险)。
  3. HTTP版本:你的原始请求用的是HTTP/1.1,示例代码中保持了一致,这没问题。

这样修改后,你的Boost.Beast请求就会像Postman一样通过HTTPS发送,直接拿到预期的JSON响应,不会再触发307重定向了。

内容的提问来源于stack exchange,提问作者user2828781

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:43:50