使用Postman向我的API发送带有承载令牌的GET请求时,我得到以下响应:
状态:401未经授权
WWW-Authenticate→Bearer error =“ invalid_token”,error_description =“未找到签名密钥”
我的解决方案包括运行IdentityServer4的授权服务器和内置于ASP.NET Core 2.2中的RESTful API
授权服务器配置有测试资源,客户端和用户。它使用测试用户的凭据响应对令牌的请求。我收到授权令牌没问题。
我的API有一个用[Authorize]操作过滤器装饰的单个值控制器。在添加过滤器之前,它会按预期响应GET请求。之后,当没有发送令牌时,它以401状态响应,但是问题是当我在请求标头中包含令牌时,我也得到了401。我收到上述答复,说未找到签名密钥。
我还配置了IdentityServer4来登录到控制台,但是在401响应之后,我实际上没有看到任何记录的消息。
在stackoverflow上提供的解决方案无法解决我的问题。我已经确认配置的API名称与我的令牌请求标头中的client_id相匹配,在本例中为“ logbookapi”。我正在使用Authorization标头密钥发送令牌,并将令牌添加为值“ Bearer”。
// API - Startup.cs
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.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.AddScoped<ILogbookRepository, LogbookRepository>();
services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options => new IdentityServerAuthenticationOptions
{
ApiName = "logbookapi",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddCors();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors(builder => builder.WithOrigins("http://localhost:6200/logbook")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials());
app.UseAuthentication();
app.UseMvc();
}
}
// Authorization Server - Startup.cs
public class Startup
{
// 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.AddIdentityServer()
.AddSigningCredential(new X509Certificate2(@"C:\Program Files\Git\usr\bin\logbookapi.pfx", "password"))
.AddInMemoryApiResources(InMemoryConfiguration.ApiResources())
.AddInMemoryClients(InMemoryConfiguration.Clients())
.AddTestUsers(InMemoryConfiguration.Users().ToList());
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
// Authorization Server - in-memory config
public static class InMemoryConfiguration
{
public static IEnumerable<ApiResource> ApiResources()
{
return new[]
{
new ApiResource("logbookapi", "Logbook API")
};
}
public static IEnumerable<Client> Clients()
{
return new[]
{
new Client
{
ClientId = "w4lkr", // unique name for this in-memory client
ClientSecrets = new[]
{
new Secret("secret".Sha256()) // client secret hashed
},
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials, // allow authorization via username/password and authorization token
AllowedScopes = new[] // which scopes this client is allowed to use
{
"logbookapi"
}
}
};
}
public static IEnumerable<TestUser> Users()
{
return new[]
{
new TestUser
{
SubjectId = "1",
Username = "mail@curtwalker.com",
Password = "password"
}
};
}
}
// API - values controller
[Route("api/[controller]")]
[Authorize]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
期望的结果是使API响应
{ "value1", "value2" }
如值控制器中所示。