ASP.NET MVC identity 使用Role來判斷前後台使用者

在新起一個ASP.NET MVC專案時,我們可以使用含有identity的範本,來作為會員登入的系統,但是往往我們前台使用identity時,後台就會選擇使用Form Authentication,或者選擇空專案,全部使用Form Authentication。

這次的練習,我是採用前後台都是使用同一套identity,藉由Role的不同來切分前後台的使用者。

Step01.將identity 加入 RoleManager 功能

在App_Start的IdentityConfig.cs 加入

//增加角色管理員相關的設定
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore): base(roleStore)
    {
    }

    public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
    {
        return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
    }
 }

在App_Start的 Startup.Auth.c s的 public void ConfigureAuth(IAppBuilder app) 加入

//增加角色的OwinContext
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

以上這兩個步驟,你的identity 就具備Role的功能了

Step02.在前後台的註冊頁加入Role的設定

public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

            //前台角色名稱
            var RoleName = "Member";
            //後台角色名稱 
            //var RoleName = "Admin";

            //判斷角色是否存在
            if (HttpContext.GetOwinContext().Gete<ApplicationRoleManager>().RoleExists(RoleName) == false)
            {
               //角色不存在,建立角色
               var role = new IdentityRole(RoleName);
               await HttpContext.GetOwinContext().Gete<ApplicationRoleManager>().CreateAsync(role);
            }
           //將使用者加入該角色
           await UserManager.AddToRoleAsync(user.Id, RoleName);
           return RedirectToAction("Index", "Home");
        }
        AddErrors(result);
    }

    // 如果執行到這裡,發生某項失敗,則重新顯示表單
    return View(model);
}

Step03.增加一個 ActionFilter,名稱為 BackendAttribute
目的:如果前台登入者,因為角色名稱不是”Admin”,所以連到後台任何路徑都會被登出,踢到登入頁。

public class BackendAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        throw new ArgumentNullException();

        //有設置AllowAnonymouse則不需要驗證
        if (SkipAuthorization(filterContext))
        return;

        var user = filterContext.RequestContext.HttpContext.User;
        var userIdentity = user.Identity;

        if (!userIdentity.IsAuthenticated)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "Login" }));
            return;
         }

        if (!user.IsInRole("Admin"))
        {
           filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "MemberLogOff" }));
            return;
        }
    }

    private static bool SkipAuthorization(AuthorizationContext filterContext)
    {
     return filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
     filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
    }
}

Step04.在後台增加一個 BaseController 套用 BackendAttribute

[Backend]
public abstract class BaseController : Controller
{
    public BaseController()
    {

    }
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *