我有两个解决方案的项目。一种是使用asp.net身份生成JWT令牌进行身份管理。在“第二个项目”中,有一些从身份项目生成的安全且可验证令牌的API,但令牌验证无效。
在邮递员中调用api存储路由时遇到此错误。我在“授权”标头中传递令牌。
处理请求时发生未处理的异常。 HttpRequestException:响应状态代码不指示成功: 404(未找到)。 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
IOException:IDX20804:无法从以下位置检索文档:“ [PII是 隐]'。 Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string 地址,CancellationToken取消)
InvalidOperationException:IDX20803:无法获取配置 来自:“ [PII隐藏]”。 Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken 取消)
堆栈查询Cookies头HttpRequestException:响应状态代码 不表示成功:404(未找到)。 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string 地址,CancellationToken取消)
显示原始异常详细信息System.Net.Http.HttpRequestException: 响应状态代码不表示成功:404(未找到)。在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()在 Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String 地址,CancelationToken取消)IOException:IDX20804:无法 从以下位置检索文档:[[PII隐藏]。 Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string 地址,CancelationToken取消) Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(string 地址,IDocumentRetriever检索器,CancellationToken取消) Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken 取消)
显示原始异常详细信息System.IO.IOException:IDX20804:无法执行 从以下位置检索文档:[[PII隐藏]。 -> System.Net.Http.HttpRequestException:响应状态代码不 表示成功:404(未找到)。在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()在 Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String 地址,CancellationToken取消)-内部异常堆栈的结尾 追踪--- Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String 地址(CancelationToken cancel) Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String 地址,IDocumentRetriever检索器,CancellationToken取消)位于 Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken 取消)InvalidOperationException:IDX20803:无法获取 配置来自:“ [PII隐藏]”。 Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken 取消) Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() Microsoft.AspNetCore.Authentication.AuthenticationHandler.AuthenticateAsync() Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext 上下文,字符串方案) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)
显示原始异常详细信息System.InvalidOperationException:IDX20803: 无法从以下位置获取配置:“ [PII隐藏]”。 -> System.IO.IOException:IDX20804:无法从以下位置检索文档: '[PII隐藏]。 ---> System.Net.Http.HttpRequestException:响应 状态代码不表示成功:404(未找到)。在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()在 Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String 地址,CancellationToken取消)-内部异常堆栈的结尾 追踪--- Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String 地址(CancelationToken cancel) Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String 地址,IDocumentRetriever检索器,CancellationToken取消)位于 Microsoft.IdentityModel.Protocols.ConfigurationManager
1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager
1.GetConfigurationAsync(CancellationToken 取消) Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() 在 Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() 在 Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync() 在 Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext 上下文,字符串方案) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)
这是我在Identity项目中的Startup.cs类。
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmonaut;
using Cosmonaut.Extensions.Microsoft.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Triverse.Identity.Models;
using Triverse.Identity.Services;
using IdentityRole = Microsoft.AspNetCore.Identity.DocumentDB.IdentityRole;
namespace Triverse.Identity
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var endPointUri = Configuration.GetValue<string>("AppSettings:EndpointUri");
var primaryKey = Configuration.GetValue<string>("AppSettings:PrimaryKey");
var databaseId = Configuration.GetValue<string>("AppSettings:DatabaseId");
var collectionId = Configuration.GetValue<string>("AppSettings:CollectionId");
var client = new DocumentClient(new Uri(endPointUri), primaryKey);
services.AddSingleton<IDocumentClient>(client);
// make sure the database exists!
var db = client.CreateDatabaseQuery().Where(d => d.Id == databaseId).AsEnumerable().FirstOrDefault()
?? client.CreateDatabaseAsync(new Database { Id = databaseId }).Result;
var databaseLink = db.SelfLink;
services.AddIdentityWithDocumentDBStores<ApplicationUser, IdentityRole>(
dbOptions =>
{
dbOptions.DocumentUrl = endPointUri;
dbOptions.DocumentKey = primaryKey;
dbOptions.DatabaseId = databaseId;
dbOptions.CollectionId = collectionId;
},
identityOptions =>
{
identityOptions.User.RequireUniqueEmail = true;
});
var cosmosSettings = new CosmosStoreSettings(databaseId, endPointUri, primaryKey);
services.AddCosmosStore<ApplicationUser>(cosmosSettings);
services.AddScoped<IAccountRepository, AccountRepository>();
services.AddTransient<ITokenService, TokenService>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Audience"],
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"])),
ValidateLifetime = true
};
cfg.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
context.Response.Headers.Add("access-control-expose-headers", "Token-Expired");
}
return Task.CompletedTask;
}
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}
}
这是我在Identity项目中的appsettings.json。
"Tokens": {
"Key": "4343@!#ewewq",
"Issuer": "http://localhost:44376/",
"Audience": "http://localhost:44385/",
"ExpiryMinutes": "55",
"ValidateLifetime": true
}
这是我在Store项目中的Startup.cs类。
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmonaut;
using Cosmonaut.Extensions.Microsoft.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Store.API.Services;
namespace Store.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var endPointUri = Configuration.GetValue<string>("AppSettings:EndpointUri");
var primaryKey = Configuration.GetValue<string>("AppSettings:PrimaryKey");
var databaseId = Configuration.GetValue<string>("AppSettings:DatabaseId");
var client = new DocumentClient(new Uri(endPointUri), primaryKey);
services.AddSingleton<IDocumentClient>(client);
var db = client.CreateDatabaseQuery().Where(d => d.Id == databaseId).AsEnumerable().FirstOrDefault()
?? client.CreateDatabaseAsync(new Database {Id = databaseId}).Result;
var databaseLink = db.SelfLink;
var cosmosSettings = new CosmosStoreSettings(databaseId, endPointUri, primaryKey);
services.AddCosmosStore<Models.Store>(cosmosSettings);
services.AddScoped<IStoreRepository, StoreRepository>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = "http://localhost:44376/";
options.RequireHttpsMetadata = false;
options.Audience = "http://localhost:44385/";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}
}
这是我在Store项目中的控制器方法。
[HttpGet]
[Authorize]
public async Task<IActionResult> GetStores()
{
var stores = new
{
Id = 1,
Name = "T-Shirt",
Price = "120.00"
};
return Ok(stores);
}
这是我从Identity项目生成的JWT令牌。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzaGFAZG9tYWluLmNvbSIsImp0aSI6IjFjYjNkNjA2LWI4MGQtNGNlZC1hMWFjLThlYmUzNzc1ZGViOSIsIlVuaXF1ZUlkIjoiZjU1ZTM2MWQtYjFkYy00MDg4LTlmYjQtMDg3ZTI4OTFjNWI1IiwidW5pcXVlX25hbWUiOiJzaGFAZG9tYWluLmNvbSIsImZpcnN0TmFtZSI6IlNoYXduIiwibmJmIjoxNTY0OTkwMjA1LCJleHAiOjE1NjQ5OTM1MDUsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDQzNzYvIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo0NDM4NS8ifQ.ZBK8Fi14QUc9ObZx7ojg7LPcl8Qs2vrQyhZi7Dbk4Gg
答案 0 :(得分:1)
Asp.NET标识本身并不完全适合该用例。您可能要看起来像Identity Server,它扩展了Identity的功能。它允许您以多种方式验证令牌,