asp.net core2.2 "用戶驗證" 和 "授權" 有很詳細和特貼心的介紹,我感興趣的主要是這兩篇: 1. "cookie身份驗證" 2. "基於角色的授權" 我的項目有兩類用戶: 1. 微信公眾號用戶,用戶名為公眾號的openid 2. 企業微信的用戶,用戶名為企業微信的userid 每類 ...
asp.net core2.2 用戶驗證 和授權有很詳細和特貼心的介紹,我感興趣的主要是這兩篇:
我的項目有兩類用戶:
- 微信公眾號用戶,用戶名為公眾號的openid
- 企業微信的用戶,用戶名為企業微信的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
修改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"); });
修改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");
}
- 返回類型為Task<IActionResult> ,因為懶得寫View,順手寫了句return Content("OK");
- 從網站複製過來代碼,AuthenticationProperties沒有設置任何內容
運行起來以後不停的調用login,百度了半天,改了各種代碼,最後把return Content("OK");改成return RedirectToAction("Index");一切OK!
揣摩原因可能是當 return Content("OK");時,自動調用AuthenticationProperties的RedirectUri,而RedirectUri為空時,自動調用自己。也不知道對不對。
這時候重視起RedirectUri,本來就要返回到returnUrl,是不是給RedirectUri賦值returnUrl就能自動跳轉?
確實,return Content("OK");時候自動跳轉了,return RedirectToAction("Index");無效。
最後把Task<IActionResult> 改成Task ,把return ...刪除,一切完美!(弱弱問一句,是不是原來就應該這樣寫?我一直在走彎路?)
求助
User有屬性Identities,看起來可以有多個Identity,如何有?