通过 ASP Core MVC、Web API 和 IdentityServer4 的身份验证?
Pass through authentication with ASP Core MVC, Web API and IdentityServer4?
我一直致力于将整体式 ASP 核心 MVC 应用程序迁移到使用服务架构设计。 MVC 前端网站使用 HttpClient
从 ASP Core Web API 加载必要的数据。一小部分前端 MVC 应用程序还需要使用 IdentityServer4(与后端 API 集成)进行身份验证。这一切都很好,直到我在 Web API 上的控制器或方法上放置了一个 Authorize
属性。我知道我需要以某种方式将用户授权从前端传递到后端才能使其正常工作,但我不确定如何进行。我尝试获取 access_token: User.FindFirst("access_token")
但它 returns 为空。然后我尝试了这个方法,我能够得到令牌:
var client = new HttpClient("url.com");
var token = HttpContext.Authentication.GetTokenAsync("access_token")?.Result;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
此方法获取令牌但仍未与后端进行身份验证API。我对这个 OpenId/IdentityServer 概念还很陌生,如有任何帮助,我们将不胜感激!
这是来自 MVC 客户端启动的相关代码 class:
private void ConfigureAuthentication(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
ExpireTimeSpan = TimeSpan.FromMinutes(60)
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "https://localhost:44348/",
RequireHttpsMetadata = false,
ClientId = "clientid",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "openid", "profile" },
GetClaimsFromUserInfoEndpoint = true,
AutomaticChallenge = true, // Required to 302 redirect to login
SaveTokens = true,
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
NameClaimType = "Name",
RoleClaimType = "Role",
SaveSigninToken = true
},
});
}
和 API 的启动 class:
// Add authentication
services.AddIdentity<ExtranetUser, IdentityRole>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
})
.AddDefaultTokenProviders();
services.AddScoped<IUserStore<ExtranetUser>, ExtranetUserStore>();
services.AddScoped<IRoleStore<IdentityRole>, ExtranetRoleStore>();
services.AddSingleton<IAuthorizationHandler, AllRolesRequirement.Handler>();
services.AddSingleton<IAuthorizationHandler, OneRoleRequirement.Handler>();
services.AddSingleton<IAuthorizationHandler, EditQuestionAuthorizationHandler>();
services.AddSingleton<IAuthorizationHandler, EditExamAuthorizationHandler>();
services.AddAuthorization(options =>
{
/* ... etc .... */
});
var serviceProvider = services.BuildServiceProvider();
var serviceSettings = serviceProvider.GetService<IOptions<ServiceSettings>>().Value;
services.AddIdentityServer() // Configures OAuth/IdentityServer framework
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryClients(IdentityServerConfig.GetClients(serviceSettings))
.AddAspNetIdentity<ExtranetUser>()
.AddTemporarySigningCredential(); // ToDo: Add permanent SigningCredential for IdentityServer
添加了 nuget package here 和以下代码来修复:
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "https://localhost:44348/",
ApiName = "api"
});
这允许 API 托管 IdentityServer4 并将其自身用作身份验证。然后在 MvcClient 中可以将不记名令牌传递给 API。
是的,您需要将 IdentityServer4.AccessTokenValidation
包添加到您的 API 项目中。并查看下面的评论
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "https://localhost:44348/", //Identity server host uri
ApiName = "api", // Valid Api resource name
AllowedScopes = scopes // scopes:List<string>
});
您应该从 API 的 StartUp class 中删除下面的代码,并替换为上面的代码 一:
services.AddIdentityServer() // Configures OAuth/IdentityServer framework
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryClients(IdentityServerConfig.GetClients(serviceSettings))
.AddAspNetIdentity<ExtranetUser>()
.AddTemporarySigningCredential();
您的身份服务器需要上述代码,而不是 API 或任何其他客户端
我一直致力于将整体式 ASP 核心 MVC 应用程序迁移到使用服务架构设计。 MVC 前端网站使用 HttpClient
从 ASP Core Web API 加载必要的数据。一小部分前端 MVC 应用程序还需要使用 IdentityServer4(与后端 API 集成)进行身份验证。这一切都很好,直到我在 Web API 上的控制器或方法上放置了一个 Authorize
属性。我知道我需要以某种方式将用户授权从前端传递到后端才能使其正常工作,但我不确定如何进行。我尝试获取 access_token: User.FindFirst("access_token")
但它 returns 为空。然后我尝试了这个方法,我能够得到令牌:
var client = new HttpClient("url.com");
var token = HttpContext.Authentication.GetTokenAsync("access_token")?.Result;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
此方法获取令牌但仍未与后端进行身份验证API。我对这个 OpenId/IdentityServer 概念还很陌生,如有任何帮助,我们将不胜感激!
这是来自 MVC 客户端启动的相关代码 class:
private void ConfigureAuthentication(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
ExpireTimeSpan = TimeSpan.FromMinutes(60)
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "https://localhost:44348/",
RequireHttpsMetadata = false,
ClientId = "clientid",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "openid", "profile" },
GetClaimsFromUserInfoEndpoint = true,
AutomaticChallenge = true, // Required to 302 redirect to login
SaveTokens = true,
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
NameClaimType = "Name",
RoleClaimType = "Role",
SaveSigninToken = true
},
});
}
和 API 的启动 class:
// Add authentication
services.AddIdentity<ExtranetUser, IdentityRole>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
})
.AddDefaultTokenProviders();
services.AddScoped<IUserStore<ExtranetUser>, ExtranetUserStore>();
services.AddScoped<IRoleStore<IdentityRole>, ExtranetRoleStore>();
services.AddSingleton<IAuthorizationHandler, AllRolesRequirement.Handler>();
services.AddSingleton<IAuthorizationHandler, OneRoleRequirement.Handler>();
services.AddSingleton<IAuthorizationHandler, EditQuestionAuthorizationHandler>();
services.AddSingleton<IAuthorizationHandler, EditExamAuthorizationHandler>();
services.AddAuthorization(options =>
{
/* ... etc .... */
});
var serviceProvider = services.BuildServiceProvider();
var serviceSettings = serviceProvider.GetService<IOptions<ServiceSettings>>().Value;
services.AddIdentityServer() // Configures OAuth/IdentityServer framework
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryClients(IdentityServerConfig.GetClients(serviceSettings))
.AddAspNetIdentity<ExtranetUser>()
.AddTemporarySigningCredential(); // ToDo: Add permanent SigningCredential for IdentityServer
添加了 nuget package here 和以下代码来修复:
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "https://localhost:44348/",
ApiName = "api"
});
这允许 API 托管 IdentityServer4 并将其自身用作身份验证。然后在 MvcClient 中可以将不记名令牌传递给 API。
是的,您需要将 IdentityServer4.AccessTokenValidation
包添加到您的 API 项目中。并查看下面的评论
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "https://localhost:44348/", //Identity server host uri
ApiName = "api", // Valid Api resource name
AllowedScopes = scopes // scopes:List<string>
});
您应该从 API 的 StartUp class 中删除下面的代码,并替换为上面的代码 一:
services.AddIdentityServer() // Configures OAuth/IdentityServer framework
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryClients(IdentityServerConfig.GetClients(serviceSettings))
.AddAspNetIdentity<ExtranetUser>()
.AddTemporarySigningCredential();
您的身份服务器需要上述代码,而不是 API 或任何其他客户端