在 Angular 7 中配置和使用 Dotnet Core Web API
Configuring and Consuming Dotnet Core Web API in Angular 7
我创建了一个 dotnet 核心 Web api,我希望在我的 angular 7 应用程序中使用它。
我运行陷入了几个问题:
- 我将我的中间件配置为使用 Jwt 身份验证(请参阅下面的部分代码);然而,当我期待 401 时,我收到了 404 状态代码。当未经授权的用户试图访问授权资源时,用户被重定向到一个不存在的登录页面。我偶然发现 post 描述了如何将 applicationcookie 覆盖为 return 401 而不是 404。它部分解决了我的问题。
- 调用 API 时,我收到 401,但我必须向请求 header 添加一个 cookie 参数。
- 在我的 Angular 应用程序中,我可以获得令牌。但是,在 API 中对授权路由的任何请求都是 returning 404,因为 header 缺少 cookie 参数。我尝试将烹饪添加到 header,但我收到错误消息 "http.js:1436 Refused to set unsafe header "cookie"。
jwt配置
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
...
};
});
将 404 覆盖为 401。
// Configure the Application Cookie
services.ConfigureApplicationCookie(options => {
// Override the default events
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = ReplaceRedirectorWithStatusCode(HttpStatusCode.Forbidden),
OnRedirectToLogin = ReplaceRedirectorWithStatusCode(HttpStatusCode.Unauthorized)
};
// Configure our application cookie
options.Cookie.Name = ".applicationname";
options.Cookie.HttpOnly = true; // This must be true to prevent XSS
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.None; // Should ideally be "Always"
options.SlidingExpiration = true;
});
Angular 拦截器的部分代码 - 根据一些评论,我删除了 cookie 并留下了 'withcredential':'true' 或'included'。这并没有什么不同。我现在硬编码 header 值。
intercept(request : HttpRequest<any>, next: HttpHandler):Observable<HttpEvent<any>>{
const headers = new HttpHeaders({
'cookie':'ASPNET_COOKIE=CfDJ8K9C4yVY5HtDnXVGM_H-y2wweqlBcYiVLelvIMw2xntKY9j_AMP1GvLahXrR4fSNhbS3AysDXYVgFCrT_-LOyHT0iofBVwdllx3UHpXvbhXrCwSofHk5CwJn3Ae5dPI9gzx-BQSxIuwTQy-SF6LcYp9ctShzvQ5D6Qxty6OHuV5yGW8ShqQ05yV0qMdxivI87j6hv2eTdTW5oAqgYEN7LRUUA9MYz7Rq8i-XSB1KirtLC0v1i5NirYdENY2XNSpRF50A5lTu2m7M1CGe8TPU1mF2RW_rV7lOHAk-HYRCl80k8vYG8SVBYMrrK3soGApWcaDteZfJtN_K_g-xhZ2etT-js0ie0nCB_OWENrBilDpl8-0AcvjqvXG5E4AFXLh47XhAbRjkIOZECZn2WU_BT6TnvCkzUevgFZDMVVx6XmqUWzYb9WESlAoWfX4RYWnaDucba_FJDlMoi3YlXEaJgDnIB1-xYSKuuGScvAt7o49595pWLyFH4Yw7qgyOeLB5YpnookVPIEmyxj3-VXe5DU7mbW1GPFZMlcFXGU9P8RwkY0LO1OJiZP0wFh4NAQ_WSockhB8t_q0vM5jOBxcLNGTricbAZcEyYTwFa-XAKNgHXqu4q7LUCID02jZpNYbdj204CIV0I1H_kUN-e2AciA8QHFCx-gpq_6Tl-1t_vOaHW1sFfxHP2fvqu3r5hlVK2Q',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoidXNlcnR3b0Bkc3NpbmMuY29tIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZW1haWxhZGRyZXNzIjoidXNlcnR3b0Bkc3NpbmMuY29tIiwiZXhwIjoxNTQ0OTE0MDQxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjIwMDEvIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDoyMDAxLyJ9.WJhyQHGxjUykg5GXrcnm2vdadxmRF83iBwwRheddu8w',
'Content-Type': 'application/json',
'withCredentials' :'true'
});
console.log('modifying headers');
const cloneRequest = request.clone({headers});
return next.handle(cloneRequest)
启用 CORS
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader() // version important for cors.
.AllowAnyMethod() //very import in order for cors to work
//.WithExposedHeaders("")
);
});
我希望有人会指出 API 的不同配置或在 angular 中设置 cookie 的方法。
已更新
我已经能够将问题缩小到下面的一段代码。当我将它们注释掉时,我在尝试访问未经授权的资源时收到 401。
services.AddIdentity<IdentityUser, IdentityRole<string>>(options =>
{
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 4;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.Password.RequireUppercase = false;
options.Password.RequiredUniqueChars = 1;
options.User.RequireUniqueEmail = false;
options.Lockout.AllowedForNewUsers = true;
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
}).AddEntityFrameworkStores<ClientPanelDbContext>()
.AddDefaultTokenProviders();
是我的失误,几经波折终于想通了。 API 工作正常,我能够获得令牌并访问受保护的资源。我错误地将安全密钥从 config.Value.key 更改为 config.Value.Issuer。它以前是有效的,所以我再也没有回到那个方法。今天早上,我注意到消息是签名无效。我去了创建令牌的方法,我意识到我的错误。我修复了,我得到了预期的 200、401、500 和 404。
我创建了一个 dotnet 核心 Web api,我希望在我的 angular 7 应用程序中使用它。 我运行陷入了几个问题:
- 我将我的中间件配置为使用 Jwt 身份验证(请参阅下面的部分代码);然而,当我期待 401 时,我收到了 404 状态代码。当未经授权的用户试图访问授权资源时,用户被重定向到一个不存在的登录页面。我偶然发现 post 描述了如何将 applicationcookie 覆盖为 return 401 而不是 404。它部分解决了我的问题。
- 调用 API 时,我收到 401,但我必须向请求 header 添加一个 cookie 参数。
- 在我的 Angular 应用程序中,我可以获得令牌。但是,在 API 中对授权路由的任何请求都是 returning 404,因为 header 缺少 cookie 参数。我尝试将烹饪添加到 header,但我收到错误消息 "http.js:1436 Refused to set unsafe header "cookie"。
jwt配置
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
...
};
});
将 404 覆盖为 401。
// Configure the Application Cookie
services.ConfigureApplicationCookie(options => {
// Override the default events
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = ReplaceRedirectorWithStatusCode(HttpStatusCode.Forbidden),
OnRedirectToLogin = ReplaceRedirectorWithStatusCode(HttpStatusCode.Unauthorized)
};
// Configure our application cookie
options.Cookie.Name = ".applicationname";
options.Cookie.HttpOnly = true; // This must be true to prevent XSS
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.None; // Should ideally be "Always"
options.SlidingExpiration = true;
});
Angular 拦截器的部分代码 - 根据一些评论,我删除了 cookie 并留下了 'withcredential':'true' 或'included'。这并没有什么不同。我现在硬编码 header 值。
intercept(request : HttpRequest<any>, next: HttpHandler):Observable<HttpEvent<any>>{
const headers = new HttpHeaders({
'cookie':'ASPNET_COOKIE=CfDJ8K9C4yVY5HtDnXVGM_H-y2wweqlBcYiVLelvIMw2xntKY9j_AMP1GvLahXrR4fSNhbS3AysDXYVgFCrT_-LOyHT0iofBVwdllx3UHpXvbhXrCwSofHk5CwJn3Ae5dPI9gzx-BQSxIuwTQy-SF6LcYp9ctShzvQ5D6Qxty6OHuV5yGW8ShqQ05yV0qMdxivI87j6hv2eTdTW5oAqgYEN7LRUUA9MYz7Rq8i-XSB1KirtLC0v1i5NirYdENY2XNSpRF50A5lTu2m7M1CGe8TPU1mF2RW_rV7lOHAk-HYRCl80k8vYG8SVBYMrrK3soGApWcaDteZfJtN_K_g-xhZ2etT-js0ie0nCB_OWENrBilDpl8-0AcvjqvXG5E4AFXLh47XhAbRjkIOZECZn2WU_BT6TnvCkzUevgFZDMVVx6XmqUWzYb9WESlAoWfX4RYWnaDucba_FJDlMoi3YlXEaJgDnIB1-xYSKuuGScvAt7o49595pWLyFH4Yw7qgyOeLB5YpnookVPIEmyxj3-VXe5DU7mbW1GPFZMlcFXGU9P8RwkY0LO1OJiZP0wFh4NAQ_WSockhB8t_q0vM5jOBxcLNGTricbAZcEyYTwFa-XAKNgHXqu4q7LUCID02jZpNYbdj204CIV0I1H_kUN-e2AciA8QHFCx-gpq_6Tl-1t_vOaHW1sFfxHP2fvqu3r5hlVK2Q',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoidXNlcnR3b0Bkc3NpbmMuY29tIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZW1haWxhZGRyZXNzIjoidXNlcnR3b0Bkc3NpbmMuY29tIiwiZXhwIjoxNTQ0OTE0MDQxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjIwMDEvIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDoyMDAxLyJ9.WJhyQHGxjUykg5GXrcnm2vdadxmRF83iBwwRheddu8w',
'Content-Type': 'application/json',
'withCredentials' :'true'
});
console.log('modifying headers');
const cloneRequest = request.clone({headers});
return next.handle(cloneRequest)
启用 CORS
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader() // version important for cors.
.AllowAnyMethod() //very import in order for cors to work
//.WithExposedHeaders("")
);
});
我希望有人会指出 API 的不同配置或在 angular 中设置 cookie 的方法。
已更新
我已经能够将问题缩小到下面的一段代码。当我将它们注释掉时,我在尝试访问未经授权的资源时收到 401。
services.AddIdentity<IdentityUser, IdentityRole<string>>(options =>
{
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 4;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.Password.RequireUppercase = false;
options.Password.RequiredUniqueChars = 1;
options.User.RequireUniqueEmail = false;
options.Lockout.AllowedForNewUsers = true;
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
}).AddEntityFrameworkStores<ClientPanelDbContext>()
.AddDefaultTokenProviders();
是我的失误,几经波折终于想通了。 API 工作正常,我能够获得令牌并访问受保护的资源。我错误地将安全密钥从 config.Value.key 更改为 config.Value.Issuer。它以前是有效的,所以我再也没有回到那个方法。今天早上,我注意到消息是签名无效。我去了创建令牌的方法,我意识到我的错误。我修复了,我得到了预期的 200、401、500 和 404。