我们可以在不使用 ASP.Net Identity 的情况下使用 MVC 5 提供的 cookie 身份验证吗?

Posted

技术标签:

【中文标题】我们可以在不使用 ASP.Net Identity 的情况下使用 MVC 5 提供的 cookie 身份验证吗?【英文标题】:Can we use cookie authentication provided by MVC 5 without using ASP.Net Identity? 【发布时间】:2019-06-25 21:09:35 【问题描述】:

我正在尝试迁移已实现自己的用户身份验证和授权逻辑的现有应用。我从 .NET MVC 开始,它包含用于身份验证和授权的 Asp.NET 身份框架。我知道我可以自定义 Asp.NET 身份以使用我现有的表。

但是是否可以在没有 Asp.NET Identity 的情况下使用 Cookie 身份验证?我发现这可用于带有以下代码的 Asp.NET 核心:

var claims = new List<Claim>

    new Claim(ClaimTypes.Name, user.Email),
    new Claim("FullName", user.FullName),
    new Claim(ClaimTypes.Role, "Administrator"),
;

var claimsIdentity = new ClaimsIdentity(
    claims, CookieAuthenticationDefaults.AuthenticationScheme);

var authProperties = new AuthenticationProperties

    //AllowRefresh = <bool>,
    // Refreshing the authentication session should be allowed.

    //ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
    // The time at which the authentication ticket expires. A 
    // value set here overrides the ExpireTimeSpan option of 
    // CookieAuthenticationOptions set with AddCookie.

    //IsPersistent = true,
    // Whether the authentication session is persisted across 
    // multiple requests. Required when setting the 
    // ExpireTimeSpan option of CookieAuthenticationOptions 
    // set with AddCookie. Also required when setting 
    // ExpiresUtc.

    //IssuedUtc = <DateTimeOffset>,
    // The time at which the authentication ticket was issued.

    //RedirectUri = <string>
    // The full path or absolute URI to be used as an http 
    // redirect response value.
;

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity), 
    authProperties);

以上代码取自微软文档link

但我找不到 Asp.NET MVC 5 的 HttpContext.SignInAsync 方法。我缺少什么吗?

【问题讨论】:

【参考方案1】:

我通过实现自己的身份来做到这一点。这样就可以轻松添加我需要的任意数量的属性。下面是一个带有自定义属性friendlyName的代码示例

public class Identity : IIdentity
    
        public Identity(int id, string name, string friendlyName, string roles)
        
            this.ID = id;
            this.Name = name;
            this.FriendlyName = friendlyName;
            this.Roles = roles;
        



  public Identity(string name, string data)
    
        if (string.IsNullOrWhiteSpace(data))
            throw new ArgumentException();

        string[] values = data.Split('|');
        if (values.Length != 3)
            throw new ArgumentException();

        this.Name = name;
        this.ID = Convert.ToInt32(values[0]);
        this.FriendlyName = values[1];
        Roles = values[2];
    

    public string AuthenticationType
    
        get  return "Custom"; 
    

    public bool IsAuthenticated
    
        get  return true; 
    

    public override string ToString()
    
        return FriendlyName;
    

    public string GetUserData()
    
        return string.Format("0|1|2", ID, FriendlyName, Roles);
    


    public int ID  get; private set; 
    public string Name  get; private set; 
    public string FriendlyName  get; private set; 
    public string Roles  get; private set; 


//in controller on login action:
        Identity id = new Identity(user.ID,  user.Username, "some friendly name", user.Roles);
        DateTime expire = DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes);
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(id.ID, user.Username, DateTime.Now, expire, false, id.GetUserData());
        string hashTicket = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashTicket);
        HttpContext.Response.Cookies.Add(cookie);

在 global.asax 中你有:

public override void Init()
        
            base.Init();
            PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
        

    void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
    
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            if (authTicket == null || authTicket.Expired)
                return;

            Identity id = new Identity(authTicket.Name, authTicket.UserData);
            Principal user = new Principal(id);
            Context.User = user;
            Thread.CurrentPrincipal = user;
        
    

【讨论】:

我还通过继承IPrincipal接口创建了自定义类来实现这一点。

以上是关于我们可以在不使用 ASP.Net Identity 的情况下使用 MVC 5 提供的 cookie 身份验证吗?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Identity 重置密码

ASP.NET Identity 重置密码

我们可以扩展 HttpContext.User.Identity 以在 asp.net 中存储更多数据吗?

ASP.NET Core Identity 系列之五

ASP.NET Core Identity系列之八

如何在不使用角色的情况下使用 ASP.NET WebAPI 实现基于声明的授权?