ASP.NET ID에서 클레임을 업데이트하는 방법은 무엇입니까?
내 MVC5 프로젝트에 OWIN 인증을 사용하고 있습니다. 이것은 나의SignInAsync
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
var AccountNo = "101";
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim(ClaimTypes.UserData, AccountNo));
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent, RedirectUri="Account/Index"}, identity);
}
보시다시피 AccountNo
클레임 목록에 추가 기사 .
이제 신청서의 어느 시점 에서이 클레임을 어떻게 업데이트 할 수 있습니까? 지금까지 다음이 있습니다.
public string AccountNo
{
get
{
var CP = ClaimsPrincipal.Current.Identities.First();
var Account= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData);
return Account.Value;
}
set
{
var CP = ClaimsPrincipal.Current.Identities.First();
var AccountNo= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData).Value;
CP.RemoveClaim(new Claim(ClaimTypes.UserData,AccountNo));
CP.AddClaim(new Claim(ClaimTypes.UserData, value));
}
}
다음 예외가 발생합니다.
' http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata : 101' 클레임을 제거 할 수 없습니다. 이 ID의 일부가 아니 거나이 ID를 포함하는 주체가 소유 한 클레임입니다. 예를 들어 역할이있는 GenericPrincipal을 만들 때 Principal이 소유합니다. 역할은 생성자에 전달되는 ID를 통해 노출됩니다. RolePrincipal에서 사용할 수 있습니다.
누군가 청구를 업데이트하는 방법을 알아낼 수 있습니까?
주어진 ClaimsIdentity를 기반으로 클레임을 추가 / 업데이트 / 읽는 확장 메서드를 만들었습니다.
namespace Foobar.Common.Extensions
{
public static class Extensions
{
public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return;
// check for existing claim and remove it
var existingClaim = identity.FindFirst(key);
if (existingClaim != null)
identity.RemoveClaim(existingClaim);
// add new claim
identity.AddClaim(new Claim(key, value));
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
}
public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return null;
var claim = identity.Claims.FirstOrDefault(c => c.Type == key);
return claim.Value;
}
}
}
그리고 그것을 사용하십시오
using Foobar.Common.Extensions;
namespace Foobar.Web.Main.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
// add/updating claims
User.AddUpdateClaim("key1", "value1");
User.AddUpdateClaim("key2", "value2");
User.AddUpdateClaim("key3", "value3");
}
public ActionResult Details()
{
// reading a claim
var key2 = User.GetClaim("key2");
}
}
}
새로 만들 수있는 ClaimsIdentity
다음 클레임 업데이트를 수행 할 수 있습니다 .
set {
// get context of the authentication manager
var authenticationManager = HttpContext.GetOwinContext().Authentication;
// create a new identity from the old one
var identity = new ClaimsIdentity(User.Identity);
// update claim value
identity.RemoveClaim(identity.FindFirst("AccountNo"));
identity.AddClaim(new Claim("AccountNo", value));
// tell the authentication manager to use this new identity
authenticationManager.AuthenticationResponseGrant =
new AuthenticationResponseGrant(
new ClaimsPrincipal(identity),
new AuthenticationProperties { IsPersistent = true }
);
}
Identity의 UserManager 및 SigninManager를 사용하여 Identity 쿠키의 변경 사항을 반영하고 선택적으로 db 테이블 AspNetUserClaims에서 클레임을 제거하는 또 다른 (비동기) 접근 방식 :
// Get User and a claims-based identity
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
var Identity = new ClaimsIdentity(User.Identity);
// Remove existing claim and replace with a new value
await UserManager.RemoveClaimAsync(user.Id, Identity.FindFirst("AccountNo"));
await UserManager.AddClaimAsync(user.Id, new Claim("AccountNo", value));
// Re-Signin User to reflect the change in the Identity cookie
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// [optional] remove claims from claims table dbo.AspNetUserClaims, if not needed
var userClaims = UserManager.GetClaims(user.Id);
if (userClaims.Any())
{
foreach (var item in userClaims)
{
UserManager.RemoveClaim(user.Id, item);
}
}
나는 그 예외도 있고 이렇게 일을 정리했습니다.
var identity = User.Identity as ClaimsIdentity;
var newIdentity = new ClaimsIdentity(identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType);
newIdentity.AddClaims(identity.Claims.Where(c => false == (c.Type == claim.Type && c.Value == claim.Value)));
// the claim has been removed, you can add it with a new value now if desired
AuthenticationManager.SignOut(identity.AuthenticationType);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, newIdentity);
MVC5를 사용할 때 여기에 추가합니다.
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(PATAUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim(ClaimTypes.Role, this.Role));
return userIdentity;
}
SignInAsync 함수에서 클레임 결과를 확인할 때 어쨌든 역할 값 사용을 수 없습니다. 하지만 ...
이 요청이 완료되면 다른 작업 (추가 요청)에서 역할에 액세스 할 수 있습니다.
var userWithClaims = (ClaimsPrincipal)User;
Claim CRole = userWithClaims.Claims.First(c => c.Type == ClaimTypes.Role);
그래서 결과로 인해 IEnumerable이 프로세스에서 업데이트 될 수 있다고 생각합니다.
.net core 2.1과 함께 최신 Asp.Net Identity를 사용하여 다음 논리로 사용자 클레임을 업데이트 할 수 있습니다.
사용자가 노래
UserClaimsPrincipalFactory
할 때SignInManager
마다 클레임이 생성을 등록합니다 .services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
UserClaimsPrincipalFactory<TUser, TRole>
표시 같은 사용자 지정 구현public class UserClaimService : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole> { private readonly ApplicationDbContext _dbContext; public UserClaimService(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) { _dbContext = dbContext; } public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user) { var principal = await base.CreateAsync(user); // Get user claims from DB using dbContext // Add claims ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("claimType", "some important claim value")); return principal; } }
나중에 응용 프로그램에서 DB에서 작업을 변경하고 인증되고 로그인 한 사용자에게 반영하고 싶을 때 다음 줄이를 달성합니다.
var user = await _userManager.GetUserAsync(User); await _signInManager.RefreshSignInAsync(user);
이렇게하면 사용자가 다시 로그인하지 최신 정보를 볼 수 있습니다. 결과를 접수에 반환하기 직전에 준비를 완료하면 모든 것이 안심하고 작업을 완료합니다.
기존의 클레임 편집하고 보안 쿠키에 대한 경쟁 조건을 만드는 대신 사용자를 자동으로 로그인하고 상태를 새로 고칩니다. :)
데이터베이스에서 클레임 세부 정보를 클릭하면 아래 코드를 사용할 수 있습니다. 또한 쿠키 값을 업데이트해야합니다.
// create a new identity
var identity = new ClaimsIdentity(User.Identity);
// Remove the existing claim value of current user from database
if(identity.FindFirst("NameOfUser")!=null)
await UserManager.RemoveClaimAsync(applicationUser.Id, identity.FindFirst("NameOfUser"));
// Update customized claim
await UserManager.AddClaimAsync(applicationUser.Id, new Claim("NameOfUser", applicationUser.Name));
// the claim has been updates, We need to change the cookie value for getting the updated claim
AuthenticationManager.SignOut(identity.AuthenticationType);
await SignInManager.SignInAsync(Userprofile, isPersistent: false, rememberBrowser: false);
return RedirectToAction("Index", "Home");
여러 쿠키, 여러 클레임
public class ClaimsCookie
{
private readonly ClaimsPrincipal _user;
private readonly HttpContext _httpContext;
public ClaimsCookie(ClaimsPrincipal user, HttpContext httpContext = null)
{
_user = user;
_httpContext = httpContext;
}
public string GetValue(CookieName cookieName, KeyName keyName)
{
var principal = _user as ClaimsPrincipal;
var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
return cp.FindFirst(((KeyName)keyName).ToString()).Value;
}
public async void SetValue(CookieName cookieName, KeyName[] keyName, string[] value)
{
if (keyName.Length != value.Length)
{
return;
}
var principal = _user as ClaimsPrincipal;
var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
for (int i = 0; i < keyName.Length; i++)
{
if (cp.FindFirst(((KeyName)keyName[i]).ToString()) != null)
{
cp.RemoveClaim(cp.FindFirst(((KeyName)keyName[i]).ToString()));
cp.AddClaim(new Claim(((KeyName)keyName[i]).ToString(), value[i]));
}
}
await _httpContext.SignOutAsync(CookieName.UserProfilCookie.ToString());
await _httpContext.SignInAsync(CookieName.UserProfilCookie.ToString(), new ClaimsPrincipal(cp),
new AuthenticationProperties
{
IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent.ToString()).Value),
AllowRefresh = true
});
}
public enum CookieName
{
CompanyUserProfilCookie = 0, UserProfilCookie = 1, AdminPanelCookie = 2
}
public enum KeyName
{
Id, Name, Surname, Image, IsPersistent
}
}
if (HttpContext.User.Identity is ClaimsIdentity identity)
{
identity.RemoveClaim(identity.FindFirst("userId"));
identity.AddClaim(new Claim("userId", userInfo?.id.ToString()));
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(HttpContext.User.Identity));
}
확장 방법은 사용자가 로그 아웃하면 이전 클레임 세트가 여전히 존재하는 모든 것을 사용자 관리자를 통해 전달하는 것과 같이 아주 잘 작동하고 로그 아웃하고 로그인해야 할 필요가있는 점을 제외하면 작동했습니다. 내 평판이 훼손되었으므로 대답 할 수 없습니다.
public static class ClaimExtensions
{
public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value, ApplicationUserManager userManager)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return;
// check for existing claim and remove it
var existingClaim = identity.FindFirst(key);
if (existingClaim != null)
{
RemoveClaim(currentPrincipal, key, userManager);
}
// add new claim
var claim = new Claim(key, value);
identity.AddClaim(claim);
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
//Persist to store
userManager.AddClaim(identity.GetUserId(),claim);
}
public static void RemoveClaim(this IPrincipal currentPrincipal, string key, ApplicationUserManager userManager)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return ;
// check for existing claim and remove it
var existingClaims = identity.FindAll(key);
existingClaims.ForEach(c=> identity.RemoveClaim(c));
//remove old claims from store
var user = userManager.FindById(identity.GetUserId());
var claims = userManager.GetClaims(user.Id);
claims.Where(x => x.Type == key).ToList().ForEach(c => userManager.RemoveClaim(user.Id, c));
}
public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return null;
var claim = identity.Claims.First(c => c.Type == key);
return claim.Value;
}
public static string GetAllClaims(this IPrincipal currentPrincipal, ApplicationUserManager userManager)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return null;
var claims = userManager.GetClaims(identity.GetUserId());
var userClaims = new StringBuilder();
claims.ForEach(c => userClaims.AppendLine($"<li>{c.Type}, {c.Value}</li>"));
return userClaims.ToString();
}
}
여기 있습니다 :
var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
var claim = (from c in user.Claims
where c.Type == ClaimTypes.UserData
select c).Single();
identity.RemoveClaim(claim);
참고 URL : https://stackoverflow.com/questions/24587414/how-to-update-a-claim-in-asp-net-identity
'ProgramingTip' 카테고리의 다른 글
localStorage 공간 계산 계산 (0) | 2020.10.18 |
---|---|
Gmail에서 메일을 작성하기위한 URL (전체 Gmail 인터페이스 및 숨은 참조, 제목 등으로 지정됨) (0) | 2020.10.18 |
PowerShell에서 한 줄씩 파일 읽기 (0) | 2020.10.18 |
Xcode 4에서 클래스 접두사를 변경하는 방법은 무엇입니까? (0) | 2020.10.18 |
방금 호출 한 오류의 줄 번호를 인쇄하는 Golang 프로그램을 어떻게 얻었습니까? (0) | 2020.10.18 |