C# Asp.Net Core 3标识-来自浏览器的JWT中不存在自定义声明
Asp.Net核心3.0C# Asp.Net Core 3标识-来自浏览器的JWT中不存在自定义声明,c#,authentication,jwt,asp.net-core-identity,asp.net-core-3.0,C#,Authentication,Jwt,Asp.net Core Identity,Asp.net Core 3.0,Asp.Net核心3.0 我正在使用ASP.NET核心web应用程序和身份验证(个人用户帐户)模板(来自Visual Studio 2019)。 我的目的是在生成的JWT中添加一些自定义声明,并在浏览器中使用它们。 为此,我扩展了UserClaimsPrincipalFactory public class MyCustomClaimsInjector : UserClaimsPrincipalFactory<ApplicationUser> { public MyCusto
我正在使用ASP.NET核心web应用程序和身份验证(个人用户帐户)模板(来自Visual Studio 2019)。
我的目的是在生成的
JWT
中添加一些自定义声明,并在浏览器中使用它们。为此,我扩展了
UserClaimsPrincipalFactory
public class MyCustomClaimsInjector : UserClaimsPrincipalFactory<ApplicationUser>
{
public MyCustomClaimsFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
{
}
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
var id = await base.GenerateClaimsAsync(user);
id.AddClaim(new Claim("my_claim1", "AdditionalClaim1"));
id.AddClaim(new Claim("my_claim2", "AdditionalClaim2"));
return id;
}
}
在从SPA客户端启动的登录阶段,调试器通过MyCustomClaimsFactory
并将声明添加到GenerateClaimsAsync
方法中的ClaimsEntity
但是,我发现奇怪的是,为什么浏览器中收到的JWT不包含由MyCustomClaimsFactory
添加的声明
我是否希望在JWT浏览器中看到自定义声明
有人能给我建议挖的方向吗。。。为什么JWT中没有这些声明
解码JWT为:
SPA应用程序:
将分享我的结果。希望这能帮助其他人 我已经实现了
IProfileService
并在ConfigureServices
中管道化了.AddProfileService()
实现
public class ProfileService : IProfileService
{
protected UserManager<ApplicationUser> _userManager;
public ProfileService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = await _userManager.GetUserAsync(context.Subject);
var claims = new List<Claim>
{
new Claim("my_FirstName", "user_FirstName"),
new Claim("my_LastName", "user_LastName")
};
context.IssuedClaims.AddRange(claims);
}
public async Task IsActiveAsync(IsActiveContext context)
{
var user = await _userManager.GetUserAsync(context.Subject);
context.IsActive = (user != null);
}
}
public类ProfileService:IProfileService
{
受保护的UserManager\u UserManager;
公共配置文件服务(UserManager UserManager)
{
_userManager=userManager;
}
公共异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
var user=await\u userManager.GetUserAsync(context.Subject);
var索赔=新列表
{
新索赔(“我的名字”、“用户名字”),
新索赔(“我的姓氏”、“用户姓氏”)
};
context.IssuedClaims.AddRange(索赔);
}
公共异步任务IsActiveAsync(IsActiveContext上下文)
{
var user=await\u userManager.GetUserAsync(context.Subject);
context.IsActive=(user!=null);
}
}
Startup.cs文件
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
.AddProfileService<ProfileService>();
services.AddIdentityServer()
.addapi授权()
.AddProfileService();
因此,现在JWT包含了我的自定义声明我不知道为什么
UserClaimsPrincipalFactory
的覆盖无法解决这个问题。我将尝试更深入地研究这些领域。所以今天我遇到了同样的问题。我以前没有使用过IdentityServer,所以我不能完全确定下面的方法是否正确,但这肯定比创建自己的IProfileService实现更容易 默认配置文件服务调用
context.AddRequestedClaims(principal.Claims);
请求的声明在您正在访问的IdentityServer API资源上定义。此资源配置是通过调用
services.AddAuthentication()
.AddIdentityServerJwt();
这将创建名为“{Environment.ApplicationName}API”的默认ApiResource配置。
此对象还包含生成JWT时要包含的声明类型集合
我找不到任何关于是否也可以在appsettings.json中设置的文档,但是您可以在启动代码中访问它
TLDR;将启动代码更改为类似以下内容:
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddIdentityServer()
.AddApiAuthorization<User, ApplicationDbContext>(options =>
{
// The options.ApiResources collection is automatically populated
// by services.AddAuthentication().AddIdentityServerJwt();
var apiResource = options.ApiResources[$"{Environment.ApplicationName}API"];
// Example: add the user's roles to the token
apiResource.UserClaims.Add(JwtClaimTypes.Role);
// Example: add another custom claim type
apiResource.UserClaims.Add("CustomClaimName");
});
services.AddAuthentication()
.AddIdentityServerJwt();
// ...
}
}
公共类启动
{
公共启动(IConfiguration配置、IWebHostEnvironment环境)
{
配置=配置;
环境=环境;
}
公共IConfiguration配置{get;}
公共IWebHostEnvironment环境{get;}
// ...
public void配置服务(IServiceCollection服务)
{
// ...
services.AddIdentityServer()
.addapi授权(选项=>
{
//options.ApiResources集合将自动填充
//通过services.AddAuthentication().AddIdentityServerJwt();
var apirource=options.apirources[$“{Environment.ApplicationName}API”];
//示例:将用户的角色添加到令牌
apiResource.UserClaims.Add(JwtClaimTypes.Role);
//示例:添加另一个自定义索赔类型
apiResource.UserClaims.Add(“CustomClaimName”);
});
services.AddAuthentication()
.AddIdentityServerJwt();
// ...
}
}
您是否继续调查为什么使用UserClaimsPrincipalFactory设置索赔不起作用?我今天遇到了同样的问题。开始在gitter asp频道聊天,但没有捕捉到有用的内容。文档太原始了,我考虑等几个月,hopin的小版本也会添加更多细节。我计划在发现真正原因后更新答案。你能给我们举一个你添加的不同索赔类型的例子吗?抱歉,我不太明白ApiResource对象的位置?我在代码中添加了注释和一个使用真实声明类型的示例,希望这能让代码更清晰。ApiResource是自动创建的“options.ApiResources”集合中的配置对象。您可以在文档中了解更多信息:似乎我在创建默认ApiResource配置的位置上出错了;我更新了代码,希望信息现在是正确的。
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddIdentityServer()
.AddApiAuthorization<User, ApplicationDbContext>(options =>
{
// The options.ApiResources collection is automatically populated
// by services.AddAuthentication().AddIdentityServerJwt();
var apiResource = options.ApiResources[$"{Environment.ApplicationName}API"];
// Example: add the user's roles to the token
apiResource.UserClaims.Add(JwtClaimTypes.Role);
// Example: add another custom claim type
apiResource.UserClaims.Add("CustomClaimName");
});
services.AddAuthentication()
.AddIdentityServerJwt();
// ...
}
}