ASP.NET Core2.2 多用戶驗證和授權


asp.net core2.2 用戶驗證授權有很詳細和特貼心的介紹,我感興趣的主要是這兩篇:

  1. cookie身份驗證
  2. 基於角色的授權

我的項目有兩類用戶:

  1. 微信公眾號用戶,用戶名為公眾號的openid
  2. 企業微信的用戶,用戶名為企業微信的userid

每類用戶中部分人員具有“Admin”角色

因為企業微信的用戶有可能同時是微信公眾號用戶,即一個人兩個名,所以需要多用戶驗證和授權。咱用代碼說話最簡潔,如下所示:

public class DemoController : Controller
{
    /// <summary>
    /// 企業微信用戶使用的模塊
    /// </summary>
    /// <returns></returns>
    public IActionResult Work()
    {
        return Content(User.Identity.Name +User.IsInRole("Admin"));
    }
    /// <summary>
    /// 企業微信管理員使用的模塊
    /// </summary>
    /// <returns></returns>
    public IActionResult WorkAdmin()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
    /// <summary>
    /// 微信公眾號用戶使用的模塊
    /// </summary>
    /// <returns></returns>
    public IActionResult Mp()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
    /// <summary>
    /// 微信公眾號管理員使用的模塊
    /// </summary>
    /// <returns></returns>
    public IActionResult MpAdmin()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
}

下面咱一步一步實現。

第一步 改造類Startup

  1. 修改ConfigureServices方法,加入以下代碼

         services.AddAuthentication
             (
             "Work"  //就是設置一個缺省的cookie驗證的名字,缺省的意思就是需要寫的時候可以不寫。另外很多時候用CookieAuthenticationDefaults.AuthenticationScheme,這玩意就是字符串常量“Cookies”,
             )
             .AddCookie
             (
             "Work", //cookie驗證的名字,“Work”可以省略,因為是缺省名
             option =>
             {
                 option.LoginPath = new PathString("/Demo/WorkLogin"); //設置驗證的路徑
                 option.AccessDeniedPath= new PathString("/Demo/WorkDenied");//設置無授權訪問跳轉的路徑
             }).AddCookie("Mp", option =>
             {
                 option.LoginPath = new PathString("/Demo/MpLogin");
                 option.AccessDeniedPath = new PathString("/Demo/MpDenied");
             });
    
  2. 修改Configure方法,加入以下代碼

         app.UseAuthentication();
    

第二步 添加驗證

    public async Task WorkLogin(string returnUrl)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, "UserId"),
            new Claim(ClaimTypes.Role, "Admin") //如果是管理員
        };

        var claimsIdentity = new ClaimsIdentity(claims, "Work");//“,"Work"”可以省略,因為是缺省名

        var authProperties = new AuthenticationProperties
        {
            AllowRefresh = true,
            //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 = false, //持久化保存,到底什么意思我也不太清楚,哪位兄弟清楚的話,盼解釋
            //IssuedUtc = <DateTimeOffset>,
            // The time at which the authentication ticket was issued.
            RedirectUri = returnUrl ?? "/Demo/Work"
        };

        await HttpContext.SignInAsync("Work", new ClaimsPrincipal(claimsIdentity), authProperties);
    }
    public IActionResult WorkDenied()
    {
        return Forbid();
    }


    public async Task MpLogin(string returnUrl)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, "OpenId"),
            new Claim(ClaimTypes.Role, "Admin") //如果是管理員
        };

        var claimsIdentity = new ClaimsIdentity(claims, "Mp");//“,"Mp"”不能省略,因為不是缺省名

        var authProperties = new AuthenticationProperties
        {
            AllowRefresh = true,
            IsPersistent = false,
            RedirectUri = returnUrl ?? "/Demo/Mp"
        };

        await HttpContext.SignInAsync("Mp", new ClaimsPrincipal(claimsIdentity), authProperties);
    }
    public IActionResult MpDenied()
    {
        return Forbid();
    }

第三步 添加授權

就是在對應的Action前面加[Authorize]

    /// <summary>
    /// 企業微信用戶使用的模塊
    /// </summary>
    /// <returns></returns>
    [Authorize(
        AuthenticationSchemes ="Work" //缺省名可以省略
        )]
    public IActionResult Work()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
    /// <summary>
    /// 企業微信管理員使用的模塊
    /// </summary>
    /// <returns></returns>
    [Authorize(AuthenticationSchemes ="Work",Roles ="Admin")]
    public IActionResult WorkAdmin()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
    /// <summary>
    /// 微信公眾號用戶使用的模塊
    /// </summary>
    /// <returns></returns>
    [Authorize(AuthenticationSchemes ="Mp")]
    public IActionResult Mp()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }
    /// <summary>
    /// 微信公眾號管理員使用的模塊
    /// </summary>
    /// <returns></returns>
    [Authorize(AuthenticationSchemes ="Mp",Roles ="Admin")]
    public IActionResult MpAdmin()
    {
        return Content(User.Identity.Name + User.IsInRole("Admin"));
    }

Ctrl+F5運行,截屏如下:

最后,講講碰到的坑和求助


一開始的驗證的代碼如下:

    public async Task<IActionResult> Login(string returnUrl)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, "UserId"),
            new Claim(ClaimTypes.Role, "Admin") //如果是管理員
        };

        var claimsIdentity = new ClaimsIdentity(claims, "Work");//“,"Work"”可以省略,因為是缺省名

        var authProperties = new AuthenticationProperties
        {
            //AllowRefresh = true,
            //IsPersistent = false,
            //RedirectUri 
        };

        await HttpContext.SignInAsync("Work", new ClaimsPrincipal(claimsIdentity), authProperties);

        return Content("OK");
    }
  1. 返回類型為Task<IActionResult> ,因為懶得寫View,順手寫了句return Content("OK");
  2. 從網站復制過來代碼,AuthenticationProperties沒有設置任何內容

運行起來以后不停的調用login,百度了半天,改了各種代碼,最后把return Content("OK");改成return RedirectToAction("Index");一切OK!

揣摩原因可能是當 return Content("OK");時,自動調用AuthenticationPropertiesRedirectUri,而RedirectUri為空時,自動調用自己。也不知道對不對。

這時候重視起RedirectUri,本來就要返回到returnUrl,是不是給RedirectUri賦值returnUrl就能自動跳轉?

確實,return Content("OK");時候自動跳轉了,return RedirectToAction("Index");無效。

最后把Task<IActionResult> 改成Task ,把return ...刪除,一切完美!(弱弱問一句,是不是原來就應該這樣寫?我一直在走彎路?)

求助

User有屬性Identities,看起來可以有多個Identity,如何有?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM