asp.net-web-api - Web api 未重定向到身份服务器登录页面
问题描述
我正在尝试使用身份服务器和 Web Api 实现 SSO
到目前为止,我已经创建了一个身份服务器项目和一个 Web Api 项目,并根据我正在学习的Pluralsight 课程对其进行了配置。自从创建本课程以来,似乎发生了一些变化,所以我必须做的一些事情与教程不匹配(这可能是我的痛点的原因,但我认为不是)。
我期望发生的是我点击了一个需要授权的控制器,如果需要,我将被重定向到身份服务器登录页面。目前我得到一个 401。我在这里查看了隐式流程的 github 示例,看来我在做正确的事情。
有人可以帮我找到我缺少的东西吗?
身份服务器
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2(@"cert.pfx", "password"))
.AddInMemoryApiResources(Resources.GetApiResources())
.AddInMemoryIdentityResources(Resources.GetIdentityResources())
.AddInMemoryClients(Clients.Get())
.AddTestUsers(Users.Get())
.AddDeveloperSigningCredential();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseDeveloperExceptionPage();//todo: add if debug
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
internal class Resources
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource> {
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource> {
new ApiResource("gateway", "Gateway Service")
};
}
}
internal class Clients
{
public static IEnumerable<Client> Get()
{
return new List<Client> {
new Client {
ClientId = "gatewayClient",
ClientSecrets = new List<Secret> { new Secret("password".Sha256())},//todo:secure password
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new List<string> { "gateway" }
},
new Client {
ClientId = "gateway_implicitClient",
ClientSecrets = new List<Secret> { new Secret("password".Sha256())},//todo:secure password
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string> {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"gateway"
},
RedirectUris = new [] { "http://localhost:49942/signin-oidc" },
PostLogoutRedirectUris = new [] { "http://localhost:49942/signout-callback-oidc" }
}
};
}
}
internal class Users
{
public static List<TestUser> Get()
{
return new List<TestUser> {
new TestUser {
SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
Username = "scott",
Password = "password"
}
};
}
}
网页接口
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
Configuration = builder.Build();
_container = new Container();
}
public IConfigurationRoot Configuration { get; }
private Container _container;
public void ConfigureServices(IServiceCollection services)
{
AddAuthentication(services);
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
{
app.UseAuthentication();
app.UseMvc();
}
private void AddAuthentication(IServiceCollection services)
{
new IdentityServerConfig(services, Configuration);
}
}
public class IdentityServerConfig
{
public IdentityServerConfig(IServiceCollection services, IConfigurationRoot configuration)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5000";
options.ApiName = "gateway_implicit";
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "gateway_implicitClient";
options.SaveTokens = true;
});
}
}
[Produces("application/json")]
[Route("api/properties")]
public class PropertiesController : AuthController
{
[HttpGet]
[Route("GetProperty/{agentId}/{propertyId}")]
public async Task<IActionResult> GetProperty(int agentId, Guid propertyId)
{
return Ok(property);
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace MyNameSpace.Controllers
{
[Route("api/[controller]")]
[Authorize]
public class AuthController : ControllerBase
{
}
}
当我打电话时,http://localhost:49942/api/properties/GetPropertySummaries/1
我可以在 VS 中看到以下输出
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: 请求开始 HTTP/1.1 GET http://localhost:49942/api/properties/GetPropertySummaries/1
'dotnet.exe' (CoreCLR: clrhost): 加载'C:\Users\me.nuget\packages\microsoft.aspnetcore.http.extensions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions。 dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.6\System.ComponentModel.Annotations.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:授权失败。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:过滤器“Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter”处的请求授权失败。微软。AspNetCore.Mvc.ChallengeResult:Information: 使用身份验证方案执行 ChallengeResult ()。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.identitymodel.tokens\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。'dotnet.exe' (CoreCLR: clrhost): 加载'C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.identitymodel.tokens.jwt\5.2.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt .dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.6\System.Xml.ReaderWriter.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.identitymodel.logging\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.identitymodel.protocols\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。“dotnet.exe”(CoreCLR:clrhost):已加载“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.identitymodel.protocols。openidconnect\5.2.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: BearerIdentityServerAuthenticationJwt 受到质疑。IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:Information:AuthenticationScheme:Bearer 被质询。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:在 142.4256 毫秒内执行操作 MyNamespace.PropertiesController.GetPropertySummaries (MyService.Gateway.Service) Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在 526.0233 毫秒内完成 401 dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: BearerIdentityServerAuthenticationJwt 受到质疑。IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:Information:AuthenticationScheme:Bearer 被质询。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:在 142.4256 毫秒内执行操作 MyNamespace.PropertiesController.GetPropertySummaries (MyService.Gateway.Service) Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在 526.0233 毫秒内完成 401 dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: BearerIdentityServerAuthenticationJwt 受到质疑。IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:Information:AuthenticationScheme:Bearer 被质询。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:在 142.4256 毫秒内执行操作 MyNamespace.PropertiesController.GetPropertySummaries (MyService.Gateway.Service) Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在 526.0233 毫秒内完成 401 信息:AuthenticationScheme:BearerIdentityServerAuthenticationJwt 受到质疑。IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:Information:AuthenticationScheme:Bearer 被质询。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:在 142.4256 毫秒内执行操作 MyNamespace.PropertiesController.GetPropertySummaries (MyService.Gateway.Service) Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在 526.0233 毫秒内完成 401 信息:AuthenticationScheme:BearerIdentityServerAuthenticationJwt 受到质疑。IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:Information:AuthenticationScheme:Bearer 被质询。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:在 142.4256 毫秒内执行操作 MyNamespace.PropertiesController.GetPropertySummaries (MyService.Gateway.Service) Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在 526.0233 毫秒内完成 401
解决方案
对于 API(而不是提供 HTML 的服务器端 Web 应用程序)返回 401 是正确的行为。这将向客户端(例如,javascript 客户端应用程序)发出它需要获取新令牌的信号。即,负责启动隐式/混合/任何登录流程以获取合适的不记名令牌的是所述 API 的客户端。
如果您采用 OpenID Connect/OAuth2 做事方式,那么您的 API 根本不会使用 cookie 进行身份验证,只会通过 AddIdentityServerAuthentication() 中间件使用不记名令牌身份验证。
推荐阅读
- git - git-diff 控制台默认颜色含义
- powershell - Powershell:使用 Import-CSV 时替换标题
- r - 计算每组、id 和时间的平均值
- javascript - 节点js中的exports.cancel预订不起作用
- machine-learning - lstm时间序列预测模型中重塑层的问题
- ios - 带有 2 个 UILabel 的 UIStackview 可以根据内容动态调整吗?
- r - 使用 R 中的时间间隔将级别添加到嵌套列表
- javascript - 在拦截中间件中获取快速参数
- cmake - 制作。我可以在主 CMakeLists.txt 中将运行时目录输出设置为模板并生成每个目标文件夹结构输出吗
- excel - VBA - 设置从集合中获取的正确工作簿