Asp.Net Core 2.1 Web Api returns 400 从 Angular 6 Web Api 发送请求以获取 access_token
Asp.Net Core 2.1 WebApi returns 400 when sending request from Angular 6 WebApp to get access_token
我有一个应用程序,在服务器端由 asp.net core 2.1 web api 表示,在客户端由 angular 6 表示。服务器端使用 OpenIddict 来支持令牌认证。主要问题是,当请求从 angular 应用程序发送到服务器以生成或刷新客户端 access_token 时,服务器响应 400(错误请求),尽管它是从邮递员一切正常。添加 Cors 策略以允许跨源请求,因为客户端和服务器端位于不同的端口,因此从 angular 到服务器的简单请求可以正常通过。
这是启动 class:
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
hostingEnvironment = env;
}
public IConfiguration Configuration { get; }
private IHostingEnvironment hostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<HospitalContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
options.UseOpenIddict();
});
services.AddCors(options => options.AddPolicy("AllowLocalhost4200", builder =>
{
builder
.WithOrigins("http://localhost:4200")
.WithHeaders("Authorization", "Content-type")
.WithMethods("Get", "Post", "Put", "Delete");
}));
services.AddCustomIdentity();
services.AddCustomOpenIddict(hostingEnvironment);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors("AllowLocalhost4200");
app.UseAuthentication();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
app.InitilizeDb();
}
}
如果有人需要查看配置,ConfigureServices 方法中的 AddCustomOpenIddict 方法:
public static IServiceCollection AddCustomOpenIddict(this IServiceCollection services,
IHostingEnvironment env)
{
services.AddOpenIddict(options =>
{
options.AddEntityFrameworkCoreStores<HospitalContext>();
options.AddMvcBinders();
options.EnableTokenEndpoint("/connect/token");
options.EnableAuthorizationEndpoint("/connect/authorize");
options.AllowRefreshTokenFlow()
.AllowImplicitFlow();
options.SetAccessTokenLifetime(TimeSpan.FromMinutes(30));
options.SetIdentityTokenLifetime(TimeSpan.FromMinutes(30));
options.SetRefreshTokenLifetime(TimeSpan.FromMinutes(60));
if (env.IsDevelopment())
{
options.DisableHttpsRequirement();
}
options.AddEphemeralSigningKey();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddOAuthValidation();
return services;
}
发送请求的Angular方法是:
public authorize(model: ILoginModel): Observable<Response> {
return this.http.post(`http://localhost:58300/connect/token`,
this.authService.authFormBody(model),
{headers: this.authService.authHeaders()});
}
与 this.authService.authFormBody 和 this.authService.authHeaders:
authHeaders(): Headers {
const headers = new Headers(
{
'Content-Type': 'application/x-www-form-urlencoded'
});
return headers;
}
authFormBody(model: ILoginModel): string {
let body = '';
body += 'grant_type=password&';
body += 'username=' + model.email + '&';
body += 'password=' + model.password + '&';
body += 'scope=OpenId profile OfflineAccess Roles';
return body;
}
我实际上是基于令牌的身份验证的新手,所以可能在配置或其他方面存在问题。将不胜感激任何解决问题的提议。
首先,尝试允许所有 headers:
稍后,准确地说,查看所有 headers 您的 angular 应用正在发送并在您的 cors 策略中允许所有这些。首先,允许 application-x-www-form-urlencoded
您的 authFormBody 方法中似乎有错字:
body += 'grant_type=password$';
这应该写成:
body += 'grant_type=password&';
我发现了一个错误,实际上是我从我的配置中删除了 AddPasswordFlow 并留下了 AllowRefreshTokenFlow() 和 AllowImplicitFlow() 并发送 grant_type=password 到未配置为接受此类的服务器赠款,那是我的错误。应该是:
services.AddOpenIddict(options =>
{
//some configs
options.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.AllowImplicitFlow();
//some configs
});
我有一个应用程序,在服务器端由 asp.net core 2.1 web api 表示,在客户端由 angular 6 表示。服务器端使用 OpenIddict 来支持令牌认证。主要问题是,当请求从 angular 应用程序发送到服务器以生成或刷新客户端 access_token 时,服务器响应 400(错误请求),尽管它是从邮递员一切正常。添加 Cors 策略以允许跨源请求,因为客户端和服务器端位于不同的端口,因此从 angular 到服务器的简单请求可以正常通过。
这是启动 class:
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
hostingEnvironment = env;
}
public IConfiguration Configuration { get; }
private IHostingEnvironment hostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<HospitalContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
options.UseOpenIddict();
});
services.AddCors(options => options.AddPolicy("AllowLocalhost4200", builder =>
{
builder
.WithOrigins("http://localhost:4200")
.WithHeaders("Authorization", "Content-type")
.WithMethods("Get", "Post", "Put", "Delete");
}));
services.AddCustomIdentity();
services.AddCustomOpenIddict(hostingEnvironment);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors("AllowLocalhost4200");
app.UseAuthentication();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
app.InitilizeDb();
}
}
如果有人需要查看配置,ConfigureServices 方法中的 AddCustomOpenIddict 方法:
public static IServiceCollection AddCustomOpenIddict(this IServiceCollection services,
IHostingEnvironment env)
{
services.AddOpenIddict(options =>
{
options.AddEntityFrameworkCoreStores<HospitalContext>();
options.AddMvcBinders();
options.EnableTokenEndpoint("/connect/token");
options.EnableAuthorizationEndpoint("/connect/authorize");
options.AllowRefreshTokenFlow()
.AllowImplicitFlow();
options.SetAccessTokenLifetime(TimeSpan.FromMinutes(30));
options.SetIdentityTokenLifetime(TimeSpan.FromMinutes(30));
options.SetRefreshTokenLifetime(TimeSpan.FromMinutes(60));
if (env.IsDevelopment())
{
options.DisableHttpsRequirement();
}
options.AddEphemeralSigningKey();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddOAuthValidation();
return services;
}
发送请求的Angular方法是:
public authorize(model: ILoginModel): Observable<Response> {
return this.http.post(`http://localhost:58300/connect/token`,
this.authService.authFormBody(model),
{headers: this.authService.authHeaders()});
}
与 this.authService.authFormBody 和 this.authService.authHeaders:
authHeaders(): Headers {
const headers = new Headers(
{
'Content-Type': 'application/x-www-form-urlencoded'
});
return headers;
}
authFormBody(model: ILoginModel): string {
let body = '';
body += 'grant_type=password&';
body += 'username=' + model.email + '&';
body += 'password=' + model.password + '&';
body += 'scope=OpenId profile OfflineAccess Roles';
return body;
}
我实际上是基于令牌的身份验证的新手,所以可能在配置或其他方面存在问题。将不胜感激任何解决问题的提议。
首先,尝试允许所有 headers:
稍后,准确地说,查看所有 headers 您的 angular 应用正在发送并在您的 cors 策略中允许所有这些。首先,允许 application-x-www-form-urlencoded
您的 authFormBody 方法中似乎有错字:
body += 'grant_type=password$';
这应该写成:
body += 'grant_type=password&';
我发现了一个错误,实际上是我从我的配置中删除了 AddPasswordFlow 并留下了 AllowRefreshTokenFlow() 和 AllowImplicitFlow() 并发送 grant_type=password 到未配置为接受此类的服务器赠款,那是我的错误。应该是:
services.AddOpenIddict(options =>
{
//some configs
options.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.AllowImplicitFlow();
//some configs
});