ASP.NET CORE中的自定义身份验证和更新声明

时间:2018-08-16 08:43:17

标签: c# asp.net asp.net-core

我正在使用ASP.NET CORE开发网站,该网站使用Claims进行用户身份验证和User Id,而其他信息保留在Claims中,这是安全性吗?

ClaimsIdentity identity = new ClaimsIdentity(
                new[]
                {
                    new Claim(ClaimTypes.Name, userInfo.Name),
                    new Claim(ClaimTypes.Surname, userInfo.Surname),
                    new Claim("Image", userInfo.Image),
                    new Claim(ClaimTypes.NameIdentifier,result.Id.ToString()),
                    new Claim(ClaimTypes.IsPersistent, loginViewModel.RememberMe.ToString())
                },
                CookieName.User);
            HttpContext.SignOutAsync(CookieName.User).Wait();
            HttpContext.SignInAsync(CookieName.User, new ClaimsPrincipal(identity),
                new AuthenticationProperties
                {
                    IsPersistent = loginViewModel.RememberMe,
                    AllowRefresh = true
                }).Wait();

有时候我需要更改用户信息,并且使用它。这是安全的方法吗?

//Get 
int id = int.Parse(new ClaimsCookie(HttpContext).GetValue(CookieName.User, KeyName.Id));

//Set Update
new ClaimsCookie(HttpContext).SetValue(CookieName.User, new[] { KeyName.Name, KeyName.Surname }, new[] { model.Name, model.Surname });

班级:

namespace ...
{
    public class ClaimsCookie
    {
        private readonly HttpContext _httpContext;
        public ClaimsCookie(HttpContext httpContext)
        {
            _httpContext = httpContext;
        }

        public string GetValue(string cookieName, string keyName)
        {
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());
            return cp.FindFirst(keyName).Value;
        }
        public async void SetValue(string cookieName, string[] keyName, string[] value)
        {
            if (keyName.Length != value.Length)
            {
                return;
            }
            if (_httpContext == null)
                return;
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());
            for (int i = 0; i < keyName.Length; i++)
            {
                if (cp.FindFirst(keyName[i]) != null)
                {
                    cp.RemoveClaim(cp.FindFirst(keyName[i]));
                    cp.AddClaim(new Claim(keyName[i], value[i]));
                }

            }
            await _httpContext.SignOutAsync(cookieName);
            await _httpContext.SignInAsync(cookieName, new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent).Value),
                    AllowRefresh = true
                });
        }
        public async void SetValue(string cookieName, string keyName, string value)
        {
            var principal = _httpContext.User;
            var cp = principal.Identities.First(i => i.AuthenticationType == cookieName.ToString());

            if (cp.FindFirst(keyName) != null)
            {
                cp.RemoveClaim(cp.FindFirst(keyName));
                cp.AddClaim(new Claim(keyName, value));
            }
            await _httpContext.SignOutAsync(cookieName);
            await _httpContext.SignInAsync(cookieName, new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent).Value),
                    AllowRefresh = true
                });
        }
    }
    public static class CookieName
    {
        public static string Company => "CompanyUserProfilCookie";
        public static string User => "UserProfilCookie";
        public static string Admin => "AdminPanelCookie";
    }

    public static class KeyName
    {
        public static string Id => ClaimTypes.NameIdentifier;
        public static string Name => ClaimTypes.Name;
        public static string Surname => ClaimTypes.Surname;
        public static string IsPersistent => ClaimTypes.IsPersistent;
        public static string Image => "Image";
    }
}

我从任何Controller都将HttpContext设置为此类。有什么办法静态HttpContext,我不想从Controller设置吗?

1 个答案:

答案 0 :(得分:0)

一种选择是从DI注入IHttpContextAccessor并从中访问HttpContext

更改ClaimsCookie构造函数以反映这一点:

private readonly HttpContext _httpContext;
public ClaimCookie(IHttpContextAccessor contextAccessor)
{
    _httpContext = contextAccessor.HttpContext;
}

接下来,您需要在Startup.ConfigureServices中注册IHttpContextAccessor和ClaimCookie:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpContextAccessor();
    services.AddTransient<ClaimCookie>();
    ...rest of code ommited...
}

然后注入您的类并使用它,而无需您自己提供HttpContext:

public class SomeController : Controller
{
    private readonly ClaimCookie _claimCookie;

    public SomeController(ClaimCookie claimCookie)
    {
        _claimCookie = claimCookie;
    }

    public async Task<IActionResult> SomeAction()
    {
        int id = int.Parse(_claimCookie.GetValue(CookieName.User, KeyName.Id));
        await _claimCookie.SetValue(CookieName.User, new[] { KeyName.Name, KeyName.Surname }, new[] { model.Name, model.Surname });
        ...
    }

还请阅读msdn's best practices in asynchronous programming,为什么不应该使用async void
关于安全性(不是专家),也不要在cookie中存储敏感数据,如果需要的话,还应该存储加密数据。