我有一个 ASP.NET Core 8 Web API 后端和一个带有 Typescript 和 Vite 的 React Js 前端。
我将 Identity 与 Entity Framework Core 用于用户管理部分。身份验证应通过 Identity 自动设置的 cookie 来完成。
这是我添加身份的地方:
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<TenantDbContext>()
.AddDefaultTokenProviders();
这是我配置身份cookie的地方:
services.ConfigureApplicationCookie(options =>
{
// Prevent redirect to login page
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.HttpOnly = true; //this is important to be true
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; //this is important to be true
// Configure other properties as needed
options.LoginPath = "/api/your-login-path";
options.LogoutPath = "/api/your-logout-path";
options.AccessDeniedPath = "/api/access-denied-path";
});
services.AddAuthorization();
在我的 React 前端,我有一个
BaseApiService
类,具有以下构造函数:
export abstract class BaseApiService {
protected readonly instance: AxiosInstance;
protected readonly servicePath: string;
protected constructor(
baseURL: string,
controllerName: string,
tenantId: string
) {
this.servicePath = `/${tenantId}/${controllerName}`;
this.instance = axios.create({
baseURL,
withCredentials: true, //this one is important
headers: {
"Content-type": "application/json",
},
});
}
为了确保这一点,我还在我的 serviceMethods 中设置了
{ withCredentials: true }
。
当我调用
Login
端点时,我可以在响应标头中看到 Set-Cookie
属性确实存在,如下所示:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://localhost:3000
Cache-Control: no-cache,no-store
Content-Type: application/json; charset=utf-8
Date: Mon, 19 Feb 2024 16:10:11 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Server: Kestrel
Set-Cookie: .AspNetCore.Identity.Application=chunks-2; path=/; secure; samesite=none; httponly
Set-Cookie: .AspNetCore.Identity.ApplicationC1=cookie_content; path=/; secure; samesite=none; httponly
Set-Cookie: .AspNetCore.Identity.ApplicationC2=cookie_content2; path=/; secure; samesite=none; httponly
我的问题是 cookie 没有保存,因此没有发送回后端。
我已经尝试过:
同样的结果,cookie没有保存,所以它们没有发送到后端,请求导致401 http代码响应。
好吧,我明白了。这对我来说有点新手错误,但事实就是如此。
因此,除了 Typescript 中的 baseApiService 类之外,我还有一个不同的 apiService 类来处理 accountController 操作。在这个特定的 apiService 上,实例化了它自己的 axios 对象,我没有设置 withCredentials: true,因此在接收 cookie 时,浏览器不会设置它们。
外卖:
如果您希望浏览器设置从后端接收的 cookie,请对接收(默认情况下生成)登录响应的 axios 实例使用 withCredentials: true 。
如果您希望浏览器将这些 cookie 发送回后端,请为发出请求的 axios 实例设置 withCredetials: true 。
使用不同的 axios(或其他)实例时要小心。
对不起大家,谢谢你们!
再见