Добавить претензию пользователя после входа в систему или изменить данные претензии в зависимости от выбора пользователя

У меня есть проект net core 2.1 с Identity.

Я пытаюсь использовать утверждения как способ хранения некоторых пользовательских данных, в основном какой-то выбор, который у них есть.

Когда пользователь впервые входит в систему, параметр задается для запроса выбора и получения индекса 0, но позже на странице бритвы пользователь может изменить его.

Теперь мне нужно сбросить данные претензии со времени входа в систему, а затем вставить новый выбор.

Q1. Когда я изменяю значение в SwitchChoice, оно перезаписывается UserClaimsFactory, потому что я «RefreshSignInAsync», так как мне удалить старое утверждение и добавить новое утверждение для этого пользователя?

Вопрос 2. Дополнительный вопрос: не создает ли приведенный ниже подход запись претензии в базе данных, а только создает данные в файлах cookie, я прав?

Startup.cs настроен:

services.AddScoped<IUserClaimsPrincipalFactory<AppUser>, UserClaimsFactory>();

UserClaimsFactory.cs настроен:

public class UserClaimsFactory : UserClaimsPrincipalFactory<AppUser, IdentityRole>
{
    private IConfiguration Configuration;
    private ApplicationDbContext _context;

    public UserClaimsFactory(
        UserManager<AppUser> userManager,
        RoleManager<IdentityRole> roleManager,
        IOptions<IdentityOptions> optionsAccessor,
        IConfiguration config,
        ApplicationDbContext context)
        : base(userManager, roleManager, optionsAccessor)
    {
        Configuration = config;
        _context = context;
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(AppUser user)
    {
        var idx = user.Id;

        List<UserChoise> ret = await _context.UserChoise.Where(s => s.AppUserId == idx)
                                .Include(s => s.InnerChoise).OrderBy(s => s.CDate)
                                .ToListAsync();

        if (ret!=null && ret.Count>0) { 
            var identity = await base.GenerateClaimsAsync(user);
            identity.AddClaim(new Claim("ABC", ret.Count > 0 ? ret[0].Name.ToString() : "NA"));
            identity.AddClaim(new Claim("XYZ", ret.Count > 0 ? ret[0].Phome.ToString() : "NA"));
            return identity;
        }
        return null;
    }
}

Login.cs настроен:

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {          
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);

        if (result.Succeeded)
        {
            var user = await _userManager.FindByNameAsync(Input.Email);

            if (!user.Active)
            {
                await _signInManager.SignOutAsync();
                return RedirectToPage("/Index");
            }
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

SwitchChoice.cs настроен:

public async Task<IActionResult> OnPostAsync()
{
    var curUser = await _userManager.GetUserAsync(User);
    if (!ModelState.IsValid)
    {
        return Page();
    }

    var identity = User.Identity as ClaimsIdentity;
    var existingClaim = identity.FindFirst("ABC");
    if (existingClaim != null)
    identity.RemoveClaim(existingClaim);

    var existingClaim2 = identity.FindFirst("XYZ");
    if (existingClaim2 != null)
    identity.RemoveClaim(existingClaim2);


    identity.AddClaim(new Claim("ABC", newVal1 != "" ? newVal1 : "NA"));
    identity.AddClaim(new Claim("XYZ", newVal2 != "" ? newVal2 : "NA"));

    await _signInManager.RefreshSignInAsync(curUser);

    return RedirectToPage("/Index");
}

person user614946    schedule 29.09.2018    source источник


Ответы (1)


Проблема в том, что вы используете утверждения для хранения данных. Утверждения или более конкретные утверждения IdentityClaims должны моделировать удостоверение. Думайте о заявках как о дне рождения, номере водительской лицензии, поле. Претензии, которые не меняются часто.

Таким образом, решение состоит в том, чтобы удалить данные из заявок и перенести их в хранилище. Это может быть частью бизнес-контекста.

Q1: Выбор может быть сохранен в файле cookie. Сохраните выбор в (бизнес) контексте в качестве запасного варианта на случай удаления файла cookie.

Q2: Заявки не сохраняются в базе данных. Он только создает ClaimsIdentity. Утверждения хранятся в токене или файле cookie, в зависимости от схемы.

person Ruard van Elburg    schedule 29.09.2018
comment
Спасибо, я не уверен, что это за сохранение выбора в (бизнес) контексте? Вы говорите, чтобы получить данные и создать файл cookie и проверить, существует ли он, а затем не создавать из базы данных? - person user614946; 29.09.2018
comment
Да, вы можете сохранить выбор в базе данных. Используйте выбор из файла cookie или, если он недоступен (например, значение = null), используйте сохраненное значение выбора и создайте новый файл cookie. - person Ruard van Elburg; 29.09.2018
comment
Но вам не обязательно использовать куки. Если вы не хотите или не можете хранить его на стороне клиента, используйте значение из базы данных. И вам не нужно сохранять его в базе данных, если достаточно файла cookie. - person Ruard van Elburg; 29.09.2018
comment
Спасибо за этот полезный совет, но я переместил логику в базу данных, чтобы ее можно было сохранить и после выхода из системы. - person user614946; 30.09.2018