【发布时间】:2018-04-17 07:11:36
【问题描述】:
我正在 .net 核心中编写一个使用 API 和网站的网络应用程序。
网络服务构建一个 JWT 令牌。 这是服务配置(删除了不必要的部分)
public void ConfigureServices(IServiceCollection services)
{
//...
var tokenValidationParameters = new TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = "ExampleIssuer",
// Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = "ExampleAudience",
// Validate the token expiry
ValidateLifetime = true,
// If you want to allow a certain amount of clock drift, set that here:
ClockSkew = TimeSpan.Zero,
};
var serialiser = services.BuildServiceProvider().GetService<IDataSerializer<AuthenticationTicket>>();
var dataProtector = services.BuildServiceProvider().GetDataProtector(new string[] {$"IronSphere.Web.Site-Auth"});
services
.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = tokenValidationParameters;
})
.AddCookie(cookie =>
{
cookie.Cookie.Name = "access_token";
cookie.TicketDataFormat = new JwtTokenValidator(
SecurityAlgorithms.HmacSha256,
tokenValidationParameters, serialiser, dataProtector);
});
//...
}
到目前为止,一切都很好。登录有效,我的网站端授权有效,我可以使用[Authorize] 属性。
现在的问题是,我在网站上登录了,但不是在 API 上。
我不能将[Authorize]-attribute 用于我的 API 方法(当然,这是有道理的)。
所以当我登录时,每次调用 API 时,我也会在标头中发送令牌(这可行,我可以在 API 控制器中读取它)。我想我需要反序列化它。
我尝试使用依赖注入将 IDataSerializer<AuthenticationTicket> 输入到我的控制器中:
services.AddSingleton<IDataSerializer<AuthenticationTicket>>(services.BuildServiceProvider().GetService<IDataSerializer<AuthenticationTicket>>());
然后从标题中获取密钥,反序列化,然后我将拥有带有声明的用户对象。但是当我尝试注入任何控制器时,它会使我的应用程序崩溃(只是一条消息,dotnet 停止工作)
知道如何在调用 api 时验证用户吗? (如果您需要我可以发布更多代码,只是不想在这里填写太多代码)
【问题讨论】:
-
明确一点:client = your webapi, server = your auth/id server issue the token?
-
@Tseng 不,不完全是。客户端只是网站,服务器是 webapi(也处理 auth-things 和令牌)
-
@Tseng 刚刚更新了它。有点误导,抱歉。
-
好的,所以客户端是一个具有视图和 cookie 身份验证的 MVC 应用程序,使用 webapi/auth 服务器作为 openid 提供程序?由于客户端不是 webapi,因此您无法使用 jwt 注册它(通常作为授权请求标头传递)。成功登录客户端后,您可以通过
string accessToken = await HttpContext.GetTokenAsync("access_token");检索令牌并将其传递给您调用的 api,即使用HttpClient和client.SetBearerToken(accessToken);后跟string content = await client.GetStringAsync("http://localhost:5001/api/example/2"); -
还要小心多次调用
services.BuildServiceProvider(),它每次都会创建一个新的 IoC 容器,并且不应在 ConfigureService 中调用它。它将在Configure方法执行之前被隐式调用。通过 new 实例化类型,这没关系,因为您在ConfigureServices这是组合根。此外,当手动设置不记名令牌时(在 HttpClient 上使用SetBearerToken方法,您必须将其内容添加为“不记名”,因此完整的标头如下所示: Authorization: Bearer xyzabc
标签: c# asp.net-core .net-core authorization asp.net-core-webapi