MVC 授權 - 多個登錄頁面 (MVC Authorization - multiple login pages)


問題描述

MVC 授權 ‑ 多個登錄頁面 (MVC Authorization ‑ multiple login pages)

I have a the following methods in an MVC Controller which redirect to the login page when a user is not logged in.

[Authorize]
public ActionResult Search() {
  return View();
}

[Authorize]
public ActionResult Edit() {
  return View();
}

Is there a quick/easy/standard way to redirect the second action to a different login page other than the page defined in the web.config file?

Or do I have to do something like

public ActionResult Edit() {
  if (IsUserLoggedIn)
    return View();
  else 
     return ReturnRedirect("/Login2");
}

‑‑‑‑‑

參考解法

方法 1:

I think it is possible by creating a custom authorization filter:  

public class CustomAuthorization : AuthorizeAttribute
{
    public string LoginPage { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.HttpContext.Response.Redirect(LoginPage);
        }
        base.OnAuthorization(filterContext);
    }
}

In your action:  

[CustomAuthorization(LoginPage="~/Home/Login1")]
public ActionResult Search() 
{
  return View();
}

[CustomAuthorization(LoginPage="~/Home/Login2")]
public ActionResult Edit() 
{
  return View();
}

方法 2:

Web.config based forms authentication does not have such a functionality built‑in (this applies to both WinForms and MVC). You have to handle it yourself (either through an HttpModule or ActionFilter, the method you mentioned or any other method)

方法 3:

I implemented the accepted answer by user434917 and even though I was being redirected correctly, I was also receiving the error "Server cannot set status after HTTP headers have been sent." in the server log.  After searching, I found this post (answer by Mattias Jakobsson) that solved the problem. I combined the answers to get this solution.

Create a custom authorization filter:

using System.Web.Mvc;
using System.Web.Routing;

namespace SomeNamespace.CustomFilters
{
    public class CustomAuthorization : AuthorizeAttribute
    {
        public string ActionValue { get; set; }
        public string AreaValue { get; set; }
        public string ControllerValue { get; set; }

        public override void OnAuthorization(AuthorizationContext context)
        {
            base.OnAuthorization(context);

            if (context.HttpContext.User.Identity.IsAuthenticated == false)
            {
                var routeValues = new RouteValueDictionary();
                routeValues["area"] = AreaValue;
                routeValues["controller"] = ControllerValue;
                routeValues["action"] = ActionValue;
                context.Result = new System.Web.Mvc.RedirectToRouteResult(routeValues);
            }
        }
    }
}

Then on your controller, use the customer attribute.

[CustomAuthorization(ActionValue = "actionName", AreaValue = "areaName", ControllerValue = "controllerName")]
public class SomeControllerController : Controller
{
    //DO WHATEVER
}

方法 4:

Yeah pretty easy! Lets say you have 2 different type of users. First typenormal users, the other one is administrators. You would like to make them login from different pages. You also want them to be able to access different ActionResults.

First you have add two different schemes. In these schemes you will define your different login pages and other options you want.

in startup.cs

       services.AddAuthentication("UserSceheme").AddCookie("UserScheme", config =>
       {
            config.LoginPath = "/UsersLogin/Login/";
            config.Cookie.Name = "UsersCookie";
        });

        services.AddAuthentication("AdminScheme").AddCookie("AdminScheme", config =>
        {
            config.LoginPath = "/AdminLogin/Login/";
            config.Cookie.Name = "AdminsCookie";
        });

Then you will define two policies. Here I called them UserAccess and AdminAccess Each policy will use the sceheme that I point. In startup.cs just after schemes add those below.

        services.AddAuthorization(options =>
        {
            options.AddPolicy("UserAccess", policy =>
            {
                policy.AuthenticationSchemes.Add("UserScheme");
                policy.RequireAuthenticatedUser();
            });
            options.AddPolicy("AdminAccess", policy =>
            {
                policy.AuthenticationSchemes.Add("AdminScheme");
                policy.RequireAuthenticatedUser();
            });
        });

The last thing we have to do is again telling the scheme we want to use when login.

     var userPrincipal = new ClaimsPrincipal(new[] {
            new ClaimsIdentity(loginClaims, "ServiceCenter")
     });
     HttpContext.SignInAsync("AdminScheme",userPrincipal);

Thats it! Now we can use these just like this; This will redirect you to the users login page.

    [Authorize(Policy = "UserAccess")]
    public IActionResult Index()
    {
        
        return View();
    }

If you have some places that you want both user types to be able to access all you have to do;

    [Authorize(Policy = "AdminAccess")]        
    [Authorize(Policy = "UserAccess")]
    public IActionResult Index()
    {
        
        return View();
    }

And finally for log‑out you also have to point the scheme

    public async Task<IActionResult> Logout()
    {
        await HttpContext.SignOutAsync("AdminScheme");
        return View();

    }

Thats it!

(by David Glennuser434917mmxjoeshmoe301meybivi)

參考文件

  1. MVC Authorization ‑ multiple login pages (CC BY‑SA 3.0/4.0)

#asp.net-mvc






相關問題

我返回集合的 Asp.net mvc 操作生成包含 system.linq.Enumerable 的 url,如何刪除它們 (My Asp.net mvc actions that return collection generate urls containing system.linq.Enumerable, how to remove them)

在 ASP.NET MVC3 中備份 MySQL 數據庫 (Backup MySQL database in ASP.NET MVC3)

jqgrid將參數傳遞給方法 (jqgrid passing parameter to method)

從局部視圖打開一個彈出窗口並重新加載父局部視圖 (open a popup from partial view and reload the parent partial view)

如何將 MVC 5 項目模板添加到 VS 2012? (How can I add the MVC 5 project template to VS 2012?)

如何避免使用 FirstOrDefault 未將對象引用設置為對象錯誤的實例? (How to avoid Object reference not set to instance of object error with FirstOrDefault?)

ASP.NET MVC:動作內的授權 - 建議的模式或者這是一種氣味? (ASP.NET MVC: Authorization inside an Action - Suggested Patterns or this is a smell?)

MVC 最佳實踐 | 您是否將鏈接構建到 Url Helper 中? (MVC Best Practices | Do you build your links into the Url Helper?)

返回包含 HTML 和 JavaScript 的 PartialView (Returning a PartialView with both HTML and JavaScript)

視圖過濾的表示類與接口 (Presentation class vs Interface for View Filtering)

C# MVC:MVC Html Helpers 與視圖中直接 HTML 的性能和優勢 (C# MVC: Performance and Advantages of MVC Html Helpers vs. Direct HTML in views)

在使用 azure 流量管理器和 azure 應用程序網關與 WAF 時實現國家級阻止 (Achieve country level blocking while using azure traffic manager and azure application gateway with WAF)







留言討論