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

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

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

個人項目有兩類用戶:cookie

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

每類用戶中部分人員具備「Admin」角色app

由於企業微信的用戶有可能同時是微信公衆號用戶,即一我的兩個名,因此須要多用戶驗證和受權。咱用代碼說話最簡潔,以下所示:asp.net

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"));
    }
}

下面咱一步一步實現。async

第一步 改造類Startupide

  1. 修改ConfigureServices方法,加入如下代碼visual-studio

    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();

第二步 添加驗證.net

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();
    }

第三步 添加受權code

就是在對應的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,如何有?

相關文章
相關標籤/搜索