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

ASP.NET Core 8.0 Web API无法获取React fetch调用设置的Session对象

ASP.NET Core 8.0 Web API无法获取React fetch调用设置的Session对象

兄弟,我瞅你这问题是Stripe跳转完成后,React调用Web API拿不到之前存在Session里的卖家信息对吧?这大概率是跨域请求的Cookie传递规则和fetch默认行为导致的,咱们一步步拆解解决:

问题核心原因

你在SignupSeller接口里把卖家数据存在了ASP.NET Core的Session中,但Session是靠Cookie来标识会话的。当用户被Stripe跳回你的React页面后,React发起的StoreStripeAccount请求默认不会自动带上Web API的Session Cookie;再加上你的CORS配置没明确允许携带凭证,Web API那边根本识别不到之前的会话,自然所有Session值都是null。另外还有个小细节:你Session里存的accountPaswword拼写错了(多了个w),不过这不是当前问题的根源,但后续要修正哦。

具体解决方案

1. 修正CORS配置,允许跨域携带凭证

首先,CORS策略里AllowAnyOrigin和AllowCredentials不能同时用,得指定你的React前端域名,不然浏览器会直接拒绝。修改Program.cs里的CORS配置:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowReactOrigin", builder =>
    {
        builder.WithOrigins("http://localhost:3000") // 你的React项目地址
               .AllowAnyMethod()
               .AllowAnyHeader()
               .AllowCredentials(); // 关键:允许携带Cookie等凭证
    });
});

然后在中间件里启用这个策略(要放在UseRouting之后,UseAuthorization之前):

app.UseCors("AllowReactOrigin");

2. React的fetch请求必须携带凭证

在React的stripecomplete页面发起fetch时,一定要加上credentials: 'include'选项,这样浏览器才会把Web API的Session Cookie带过去:

// 示例fetch代码
fetch('http://localhost:xxxx/StoreStripeAccount', {
    method: 'POST',
    credentials: 'include', // 核心:强制携带Cookie
    headers: {
        'Content-Type': 'application/json',
    },
    // 如果需要传其他数据可以加body,这里暂时不需要
})
.then(res => res.json())
.then(data => {
    console.log(data);
    // 后续逻辑
})
.catch(err => console.error('请求出错:', err));

3. 调整Session Cookie的跨域兼容配置

在Program.cs的AddSession里,给Cookie加上跨域需要的SameSite和Secure配置,不然浏览器可能因为隐私策略拒绝存储Cookie:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromSeconds(31536000);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
    options.Cookie.SameSite = SameSiteMode.None; // 跨域场景必须设置为None
    // 本地开发用None,生产环境一定要用Always(HTTPS环境)
    options.Cookie.SecurePolicy = CookieSecurePolicy.None; 
});

4. 更可靠的备选方案:用临时数据库存储替代Session

其实Session在跨第三方跳转(比如Stripe)的场景下,很容易因为浏览器的SameSite限制、隐私模式等原因失效。更稳妥的方式是把临时数据存在数据库里,用唯一ID传递:

  • 在SignupSeller接口里生成一个GUID,把卖家信息和Stripe账户ID存在临时表,然后把这个GUID拼在Stripe的ReturnUrl里:
var tempRecordId = Guid.NewGuid().ToString();
// 假设你有个临时表的仓储,把数据存进去
await tempSellerRepository.SaveTempData(tempRecordId, account.Id, signupSellerInput);

// 修改Stripe的返回链接,带上这个临时ID
var optionsAccountLink = new AccountLinkCreateOptions
{
    Account = account.Id,
    RefreshUrl = "http://localhost:3000/stripeerror",
    ReturnUrl = $"http://localhost:3000/stripecomplete?tempId={tempRecordId}",
    Type = "account_onboarding",
};
  • React页面获取URL里的tempId,然后在fetch时传给Web API:
// 从URL参数里拿tempId
const urlParams = new URLSearchParams(window.location.search);
const tempId = urlParams.get('tempId');

fetch('http://localhost:xxxx/StoreStripeAccount', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ tempId: tempId })
})
  • StoreStripeAccount接口通过tempId从临时表取数据,完成存储后删除临时记录:
// 先定义接收参数的模型
public class TempIdRequest
{
    public string TempId { get; set; }
}

[HttpPost]
[Route("StoreStripeAccount")]
public async Task<IActionResult> StoreStripeAccount([FromBody] TempIdRequest request)
{
    var tempData = await tempSellerRepository.GetTempData(request.TempId);
    if (tempData == null)
    {
        return Ok(new { error = "无效的临时记录" });
    }

    // 用临时数据创建用户和关联Stripe账户
    var userId = Guid.NewGuid().ToString();
    var user = await userRepository.StoreUser(userId, tempData.Email, tempData.Password, tempData.FirstName, tempData.LastName, tempData.BusinessName, tempData.Country);
    await stripeRepository.StoreConnectedAcount(user.Id, tempData.AccountId);

    // 删除临时数据,避免冗余
    await tempSellerRepository.DeleteTempData(request.TempId);
    return Ok(new { success = "accountAdded" });
}

这个方案完全绕开了Session的跨域问题,稳定性更高,生产环境更推荐用这个。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:35:28