Asp.net Core 2.0+React.js Cookie认证同构Fetch触发无限循环问题
嘿,我帮你捋清楚这个问题——你遇到的无限循环,核心原因有两个:一是React里的fetch请求默认不会携带认证Cookie,导致后端每次都判定你未登录;二是后端对API请求依然返回登录页的重定向,前端拿到重定向后的HTML内容,没法正确解析成JSON,进而触发重复请求,形成死循环。下面分两步解决:
1. 给Fetch请求加上携带Cookie的配置
默认情况下fetch不会自动把Cookie发给服务器,你得显式加个credentials参数。修改你的请求代码:
let url = "ProposalData/GetProposals?" + $.param({ take: 10, skip: 0 }) fetch(url, { credentials: 'include' // 关键:让请求带上认证Cookie }) .then(response => { // 额外加个判断:如果后端返回401未认证,手动跳登录页 if (response.status === 401) { window.location.href = '/Account/Login/'; return Promise.reject('用户未登录'); } return response.json() as Promise<ProposalData[]>; }) .then(data => { this.setState({ proposalDatas: data, loading: false }); }) .catch(err => console.error('请求出错啦:', err));
这里credentials的取值可以根据你的场景选:
'include': 不管是同域还是跨域请求,都带上Cookie'same-origin': 只有同域请求才带Cookie(如果你的React和API是同域名,用这个也没问题)
2. 后端改配置:API请求返回401,别返回重定向
你现在的Cookie认证配置,对所有未登录请求都返回登录页重定向,但API请求是AJAX,不需要HTML页面,要的是状态码提示。修改Startup.cs里的Cookie配置:
.AddCookie(options => { options.ExpireTimeSpan = TimeSpan.FromMinutes(19); options.AccessDeniedPath = "/Account/Forbidden/"; options.LoginPath = "/Account/Login/"; // 新增这段:区分API请求和页面请求 options.Events = new CookieAuthenticationEvents { OnRedirectToLogin = context => { // 判断是不是AJAX/API请求 if (context.Request.Headers["X-Requested-With"] == "XMLHttpRequest" || context.Request.Path.StartsWithSegments("/ProposalData")) // 或者你API的前缀路径 { // API请求直接返回401状态码 context.Response.StatusCode = StatusCodes.Status401Unauthorized; return Task.CompletedTask; } // 普通页面请求还是正常跳登录页 context.Response.Redirect(context.RedirectUri); return Task.CompletedTask; } }; });
这样改了之后,当fetch请求没带Cookie时,后端会返回401,前端捕获到这个状态码就手动跳登录,不会再拿到登录页的HTML去解析成JSON,自然就终止循环了。
额外要检查的点
- 如果你的React和API是跨域部署的,记得在Startup里配置CORS,要开启
AllowCredentials(),不然Cookie还是带不过去 - 确认登录时生成的Cookie的
SameSite属性,Asp.net Core 2.0默认是Lax,要是跨域场景可能需要改成None(但要配合Secure=true,也就是HTTPS环境)
内容的提问来源于stack exchange,提问作者erhan355
相关产品推荐
相关产品推荐

