我的设置,
-
使用MVC标识存储用户的IdentityServer,使用
dotnet new mvc -au Individual
创建并应用在localhost 5000中运行的http://docs.identityserver.io/en/release/quickstarts/0_overview.html教程 . -
客户端应用程序,但现在我正在使用邮递员进行测试 .
-
使用
dotnet new webapi
创建的WEB API,在localhost 5001中运行 .
IdentityServer资源和客户端配置如下,请注意我正在使用引用标记:
public static IEnumerable<IdentityResource> GetIdentityResources() {
return new List<IdentityResource>{ new IdentityResources.OpenId() };
}
public static IEnumerable<ApiResource> GetApiResources() {
return new List<ApiResource>{
new ApiResource("api_resource", "API Resource") {
Description= "API Resource Access",
ApiSecrets= new List<Secret> { new Secret("apiSecret".Sha256()) },
}
};
}
public static IEnumerable<Client> GetClients() {
return new List<Client>{
new Client {
ClientId= "angular-client",
ClientSecrets= { new Secret("secret".Sha256()) },
AllowedGrantTypes= GrantTypes.ResourceOwnerPassword,
AllowOfflineAccess= true,
AccessTokenType = AccessTokenType.Reference,
AlwaysIncludeUserClaimsInIdToken= true,
AllowedScopes= { "api_resource" }
}
}
密码和用户与邮递员一起发送,收到的令牌也会通过邮递员发送到WEB API,如调用 localhost:5001/v1/test
,并在选项 bearer token
中粘贴令牌 .
在API Startup中,在ConfigureServices中我添加以下行
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority= "http://localhost:5000";
options.ApiName= "api_resource";
options.ApiSecret = "apiSecret";
});
我在控制器中获得用户的ID如下:
public async Task<IActionResult> Get(int id) {
var discoveryClient = new DiscoveryClient("http://localhost:5000");
var doc = await discoveryClient.GetAsync();
var introspectionClient = new IntrospectionClient(
doc.IntrospectionEndpoint,
"api_resource",
"apiSecret");
var token= await HttpContext.GetTokenAsync("access_token");
var response = await introspectionClient.SendAsync(
new IntrospectionRequest { Token = token });
var userId = response.Claims.Single(c => c.Type == "sub").Value;
}
问题本身就是, am I using the right path to get the Id from the reference token? ,因为现在它有效,但我不想错过任何东西,特别认为这是一个安全问题 .
我也问,因为我看过别人用过
string userId = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
这更直接,但似乎不适合参考标记 .
提前致谢 .
1 回答
在受
[Authorize]
属性保护的控制器操作中,您只需直接从ClaimsPrinciple
获取声明,而无需通过手动发现客户端 . 声明原则在控制器内部简单地用User
轻易别名 .参考令牌它可以正常工作 . 访问
sub
声明应该没有问题 .编辑:正如我在下面的评论中提到的,我倾向于使用标准JwtClaimTypes并在
ClaimsPrinciple
上创建一些扩展方法,例如:要么
...所以在我受保护的行动中,我可以简单地使用
User.GetEmail()
来获取索赔值 . 值得注意的是,任何检索索赔值的方法只有在索赔确实存在的情况下才有效 . 即,要求ZoneInfo声明将不起作用,除非该声明首先作为令牌请求的一部分被请求 .