ASP.NET Core 2.1:如何在控制器代码中访问"action claims"(尤其是在用户注册时)?
ASP.NET Core 2.1: how to access "action claims" in the controller code (especially during user registration)?
使用 Core Identity OAuth2 身份验证(并检索用户信息)最后一个 MS 样本使用这样的代码:
options.Events = new OAuthEvents
{
// ...
OnCreatingTicket = async (OAuthCreatingTicketContext context) =>
{
var userInfo = // ..
context.RunClaimActions(userInfo);
}
}
MS 称之为 "Action Claims".
但是以后如何在控制器代码中访问这些操作声明?
具体来说,如何在 "Core Identity 2.1" 生成的 Razor 页面中访问它们 用户外部登录 OnGetCallbackAsync
// ExternalLogin.cshtml.cs
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
var claimsIdentity = User.Identity as ClaimsIdentity;
var claimsPrincipal = User.Identity as ClaimsPrincipal; // null
// claimsIdentity doesn't contains oauth target claims (since this new not registered yet user?)
// ..
var signInResult = await _signInManager.ExternalLoginSignInAsync(...);
if (signInResult.Succeeded)
{
}else // means yet not registered locally
{
// HOW TO ACCESS ACTION CLAIMS THERE?
// or how to get authentication token to get user info manually...
}
}
P.S.
除了 asnwer:RunClaimActions
应该与 MapJsonKey
一起使用
serviceCollection.AddAuthentication().AddOAuth(options =>
{
// ...
// https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.claims.claimtypes_members.aspx
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey("SalesforceOrganizationId", "organization_id");
然后可以像普通用户声明一样访问用户信息字段。因此 "Action claims" 不是 "special type of claims" 而只是 "yet another ASP MVC magic".
也不要忘记 options.SaveTokens = true;
只有有了它,您才能获得令牌
var info = await _signInManager.GetExternalLoginInfoAsync();
var token = info.AuthenticationTokens ()[0];
并从其他连接的服务中获取更多信息。
我在官方文档中看到过这个例子。
引用Persist additional claims and tokens from external providers in ASP.NET Core
您首先必须在配置身份验证提供程序时映射所需的声明
文档示例使用了 Google,它映射用户数据键并创建声明
In the provider's options, specify a MapJsonKey
for each key in the external provider's JSON user data for the app identity to read on sign in.
启动
services.AddAuthentication().AddGoogle(options => {
//....
options.ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
//...map other claims/claim types
//...
}
从那里您应该能够通过 ExternalLoginInfo.Principal
访问声明,其中 ClaimsPrincipal
代表与登录关联的用户。
ExternalLogin.cshtml.cs
//Executes when a previously registered user signs into the app.
public async Task<IActionResult> OnGetCallbackAsync(
string returnUrl = null, string remoteError = null) {
if (remoteError != null) {
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null) {
return RedirectToPage("./Login");
}
// Sign in the user with this external login provider if the user
// already has a login
var result = await _signInManager.ExternalLoginSignInAsync(
info.LoginProvider, info.ProviderKey, isPersistent: false,
bypassTwoFactor : true);
if (result.Succeeded) {
// Store the access token and resign in so the token is included in
// in the cookie
var user = await _userManager.FindByLoginAsync(info.LoginProvider,
info.ProviderKey);
// What is the gender of this user if present
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Gender)) {
var gender = info.Principal.FindFirst(ClaimTypes.Gender);
//...use gender
}
var props = new AuthenticationProperties();
props.StoreTokens(info.AuthenticationTokens);
await _signInManager.SignInAsync(user, props, info.LoginProvider);
_logger.LogInformation(
"{Name} logged in with {LoginProvider} provider.",
info.Principal.Identity.Name, info.LoginProvider);
return LocalRedirect(Url.GetLocalUrl(returnUrl));
}
if (result.IsLockedOut) {
return RedirectToPage("./Lockout");
} else {
// If the user does not have an account, then ask the user to
// create an account
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) {
Input = new InputModel {
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}
return Page();
}
}
查看代码中的注释并注意对info.Principal.Identity
的访问,其中应包含与当前用户退出后关联的声明。
使用 Core Identity OAuth2 身份验证(并检索用户信息)最后一个 MS 样本使用这样的代码:
options.Events = new OAuthEvents
{
// ...
OnCreatingTicket = async (OAuthCreatingTicketContext context) =>
{
var userInfo = // ..
context.RunClaimActions(userInfo);
}
}
MS 称之为 "Action Claims".
但是以后如何在控制器代码中访问这些操作声明?
具体来说,如何在 "Core Identity 2.1" 生成的 Razor 页面中访问它们 用户外部登录 OnGetCallbackAsync
// ExternalLogin.cshtml.cs
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
var claimsIdentity = User.Identity as ClaimsIdentity;
var claimsPrincipal = User.Identity as ClaimsPrincipal; // null
// claimsIdentity doesn't contains oauth target claims (since this new not registered yet user?)
// ..
var signInResult = await _signInManager.ExternalLoginSignInAsync(...);
if (signInResult.Succeeded)
{
}else // means yet not registered locally
{
// HOW TO ACCESS ACTION CLAIMS THERE?
// or how to get authentication token to get user info manually...
}
}
P.S.
除了 asnwer:RunClaimActions
应该与 MapJsonKey
serviceCollection.AddAuthentication().AddOAuth(options =>
{
// ...
// https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.claims.claimtypes_members.aspx
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey("SalesforceOrganizationId", "organization_id");
然后可以像普通用户声明一样访问用户信息字段。因此 "Action claims" 不是 "special type of claims" 而只是 "yet another ASP MVC magic".
也不要忘记 options.SaveTokens = true;
只有有了它,您才能获得令牌
var info = await _signInManager.GetExternalLoginInfoAsync();
var token = info.AuthenticationTokens ()[0];
并从其他连接的服务中获取更多信息。
我在官方文档中看到过这个例子。
引用Persist additional claims and tokens from external providers in ASP.NET Core
您首先必须在配置身份验证提供程序时映射所需的声明
文档示例使用了 Google,它映射用户数据键并创建声明
In the provider's options, specify a
MapJsonKey
for each key in the external provider's JSON user data for the app identity to read on sign in.
启动
services.AddAuthentication().AddGoogle(options => {
//....
options.ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
//...map other claims/claim types
//...
}
从那里您应该能够通过 ExternalLoginInfo.Principal
访问声明,其中 ClaimsPrincipal
代表与登录关联的用户。
ExternalLogin.cshtml.cs
//Executes when a previously registered user signs into the app.
public async Task<IActionResult> OnGetCallbackAsync(
string returnUrl = null, string remoteError = null) {
if (remoteError != null) {
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null) {
return RedirectToPage("./Login");
}
// Sign in the user with this external login provider if the user
// already has a login
var result = await _signInManager.ExternalLoginSignInAsync(
info.LoginProvider, info.ProviderKey, isPersistent: false,
bypassTwoFactor : true);
if (result.Succeeded) {
// Store the access token and resign in so the token is included in
// in the cookie
var user = await _userManager.FindByLoginAsync(info.LoginProvider,
info.ProviderKey);
// What is the gender of this user if present
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Gender)) {
var gender = info.Principal.FindFirst(ClaimTypes.Gender);
//...use gender
}
var props = new AuthenticationProperties();
props.StoreTokens(info.AuthenticationTokens);
await _signInManager.SignInAsync(user, props, info.LoginProvider);
_logger.LogInformation(
"{Name} logged in with {LoginProvider} provider.",
info.Principal.Identity.Name, info.LoginProvider);
return LocalRedirect(Url.GetLocalUrl(returnUrl));
}
if (result.IsLockedOut) {
return RedirectToPage("./Lockout");
} else {
// If the user does not have an account, then ask the user to
// create an account
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) {
Input = new InputModel {
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}
return Page();
}
}
查看代码中的注释并注意对info.Principal.Identity
的访问,其中应包含与当前用户退出后关联的声明。