使用Asp.net core和Identityserver 4从浏览器得到401,从邮差得到200



我尝试了一切,当我试图从react应用程序到达我的api时,我一直得到401错误。我的Api是由身份服务器保护的asp.net核心。

从邮差,我可以请求访问令牌和调用api,它工作得很好。从浏览器,我可以获得一个有效的访问令牌,但任何api调用失败的401。

在浏览器中失败的请求,在邮差上可以正常工作(从开发工具复制为cUrl,然后导入邮差)。

我已经尝试了http和https,我已经检查了启动时元素的顺序,我已经配置了CORS…没有。

我使用相同的web应用程序作为身份服务器和Api服务器。

我的启动文件:

using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Pesabooks.Api.Common;
using Pesabooks.Application;
using Pesabooks.Application.Common.Interfaces;
using Pesabooks.Domain.Session;
using Pesabooks.Infrastructure;
using System.Threading.Tasks;
namespace Pesabooks.Api
{
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://localhost:3000").AllowAnyMethod().AllowAnyHeader();
});
});

services.AddControllersWithViews()
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<IPesabooksDbContext>()); ;
services.AddApplication();
services.AddInfrastructure(Configuration, Environment);
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie("Cookies", options =>
{
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
});
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
};
//options.Audience = "pesabooks";
options.RequireHttpsMetadata = false;
});
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});

services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Pesabooks.Api", Version = "v1" });
c.OperationFilter<AddRequiredHeaderParameter>();
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Strict });
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Pesabooks.Api v1"));
}
app.UseCustomExceptionHandler();
// app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();
app.UseIdentityServer();
app.UseTenantMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllers();
});
}
}
}

这是我的identityserver客户端设置:

{
"IdentityServer": {
"Clients": [
{
"ClientId": "Pesabooks.WebApp",
"ClientName": "Pesabooks Web App",
"AllowedGrantTypes": [ "implicit" ],
"AllowedScopes": [ "openid", "profile", "api" ],
"RequireClientSecret": false,
"RedirectUris": [ "http://localhost:3000/signin-oidc" ],
"PostLogoutRedirectUris": [ "http://localhost:3000/signout-oidc" ],
"AllowedCorsOrigins": [ "http://localhost:3000" ],
"AllowAccessTokensViaBrowser": true,
"Enabled": true
},
{
"ClientName": "Pesabooks.IntegrationTests",
"ClientId": "Pesabooks.IntegrationTests",
"AllowedGrantTypes": [ "password" ],
"AllowedScopes": [ "openid", "profile" ],
"ClientSecrets": [ { "Value": "*****" } ],
"Enabled": true
},
{
"ClientName": "Postman",
"ClientId": "postman",
"RequirePkce": false,
"AllowedGrantTypes": [ "authorization_code" ],
"AllowOfflineAccess": true,
"IdentityTokenLifetime": 86400,
"AccessTokenLifetime": 86400,
"RedirectUris": [ "https://www.getpostman.com/oauth2/callback" ],
"PostLogoutRedirectUris": [ "https://www.getpostman.com" ],
"AllowedCorsOrigins": [ "https://www.getpostman.com" ],
"AllowedScopes": [ "openid", "profile", "email", "api" ],
"ClientSecrets": [ { "Value": "*****" } ],
"AllowAccessTokensViaBrowser": true,
"RequireConsent": false,
"EnableLocalLogin": true,
"Enabled": true
}
]
}
}

这是一个在浏览器中失败的请求的例子,但在postman中可以工作:

curl 'http://localhost:5000/Account/Login?ReturnUrl=%2Fapi%2FAccounts%3FOnlySavings%3Dfalse%26IncludeDeactivated%3Dfalse' 
-H 'Connection: keep-alive' 
-H 'Accept: application/json' 
-H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjdBQjI4QUQzNEQ3OUMwOTNCMkY2NjZEQUU5MTYwQzczIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE2MTE1MDA4NDgsImV4cCI6MTYxMTUwNDQ0OCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwL3Jlc291cmNlcyIsImNsaWVudF9pZCI6IlBlc2Fib29rcy5XZWJBcHAiLCJzdWIiOiIxIiwiYXV0aF90aW1lIjoxNjExNTAwODE4LCJpZHAiOiJsb2NhbCIsImp0aSI6IkYzRkE5MUIxRUM0MzIyNkRBNEZCNDU1QjQ2MTE1MzI5Iiwic2lkIjoiQTE3RDVDQjY3QTIxMDc0MjE4QzgyNTE1RjI5QjdGQUYiLCJpYXQiOjE2MTE1MDA4NDgsInNjb3BlIjpbIm9wZW5pZCIsInByb2ZpbGUiLCJhcGkiXSwiYW1yIjpbInB3ZCJdfQ.gGmUUmZNZLjhyY47diPXQHGXO0k1B8mss8FIdQuecFmp-SxRFls6nF7fU3bqQdQcadpIrZEjDGG2wth8IZIqg82K5L4jr9Nt8Rp8JMdvC-zn7TbHKV670QSYF6NIq5AKWNMi86oNfk9QYEIjM7p5DWjzSjH5LAmINQjwCNG0QhXccSqbUkmVxxsYQkCOfZnlsshrswP41ocNs1s_363v070Tc6ayrxBSYiqM5AbLs_5y4iSXgP1TzWdwxcavBng-vEA0lp5hU0ZNggmBid_GOrgKRfHNzv8518RfHtpa1VwptdkRMiba18t-HNezMw7WMh432Q6RxRvJGW6iq7S8eg' 
-H 'psbk-tenant: 5' 
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' 
-H 'Sec-GPC: 1' 
-H 'Origin: http://localhost:3000' 
-H 'Sec-Fetch-Site: same-site' 
-H 'Sec-Fetch-Mode: cors' `
-H 'Sec-Fetch-Dest: empty' 
-H 'Referer: http://localhost:3000/' 
-H 'Accept-Language: en-US,en;q=0.9' 
--compressed

这是我在日志中得到的:

[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was not authenticated.
[11:28:48 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CORS request made for path: /.well-known/openid-configuration from origin: http://localhost:3000
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was not authenticated.
[11:28:48 Debug] IdentityServer4.Services.InMemoryCorsPolicyService
Client list checked and origin: http://localhost:3000 is allowed
[11:28:48 Information] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was challenged.
[11:28:48 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CorsPolicyService allowed origin: http://localhost:3000
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was not authenticated.
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was not authenticated.
[11:28:48 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration matched to endpoint type Discovery
[11:28:48 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
[11:28:48 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
[11:28:48 Debug] IdentityServer4.Endpoints.DiscoveryEndpoint
Start discovery request
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was successfully authenticated.
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was successfully authenticated.
[11:28:48 Debug] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application was successfully authenticated.
[11:28:48 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /connect/checksession matched to endpoint type Checksession
[11:28:48 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Checksession, successfully created handler: IdentityServer4.Endpoints.CheckSessionEndpoint
[11:28:48 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.CheckSessionEndpoint for /connect/checksession
[11:28:48 Debug] IdentityServer4.Endpoints.CheckSessionEndpoint
Rendering check session result

提前谢谢你。

为了帮助您调试,您应该配置日志并显示其中的调试输出。在IdentityServer解决方案中,您通常在program.cs类中控制它,如下面的示例所示:

只需将日志级别设置为"调试",即可查看操作中的更多信息。

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
// uncomment to write to Azure diagnostics stream
//.WriteTo.File(
//    @"D:homeLogFilesApplicationidentityserver.txt",
//    fileSizeLimitBytes: 1_000_000,
//    rollOnFileSizeLimit: true,
//    shared: true,
//    flushToDiskInterval: TimeSpan.FromSeconds(1))
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
.CreateLogger();

我做了一个测试,创建了一个单独的web api项目,它马上就工作了。

使用同一服务器的身份服务器和我的api是一个坏主意,由于某些原因,这是行不通的。

解决方案:有一个专门的web应用程序的身份服务器

最新更新