Ich habe gelesen
Wie einfach umleiten, wenn nicht in MVC 3 authentifiziert? und Umleitung zur AccessDenied-Seite, wenn der Benutzer nicht autorisiert ist aber der Link aus einer Antwort (bedeutet http://wekeroad.com/2008/03/12/aspnet-mvc-securing-your -controller-actions/ ) funktioniert nicht.
Ich setze
[Authorize(Users = "test")]
public class RestrictedPageController: Controller
{
public ActionResult Index()
{
return View();
}
....
}
Und in meiner web.config habe ich schon
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
entsprechend mit https://stackoverflow.com/a/6770583/998696
Wenn ich jedoch auf /RestrictedPage/Index
zugreifen möchte, muss es mich auf eine andere Seite (von einem anderen Controller) umleiten. Stattdessen sieht der Fehler folgendermaßen aus:
Server Error in '/Project' Application.
The view 'LogOn' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Account/LogOn.aspx
~/Views/Account/LogOn.ascx
~/Views/Shared/LogOn.aspx
~/Views/Shared/LogOn.ascx
~/Views/Account/LogOn.cshtml
~/Views/Account/LogOn.vbhtml
~/Views/Shared/LogOn.cshtml
~/Views/Shared/LogOn.vbhtml
Vor dem Anmelden wird das Seitenformular "Logon
" korrekt angezeigt. Beim Zugriff auf die Seite "/RestrictedPage/Index
" wird jedoch der obige Fehler angezeigt. Ich kann mich mit einem anderen Benutzer einloggen, der zum Zugriff auf die Seite RestrictedPage
berechtigt ist.
Wo liegt mein Fehler und wie richten Sie die Umleitung ein?
Das Standardattribut Authorize
verhält sich so, dass, wenn der Benutzer nicht authentifiziert oder authentifiziert, aber nicht autorisiert ist, der Statuscode als 401 (UnAuthorized) gesetzt wird. Wenn der Filter den Statuscode als 401 festlegt, überprüft das ASP.NET-Framework, ob für die Website die Formularauthentifizierung aktiviert ist und ob dann an den dort eingerichteten loginUrl
-Parameter umgeleitet wird.
Wenn Sie dieses Verhalten ändern möchten, sagen Sie, dass Sie den Benutzer an einen AccessDenied
-Controller umleiten möchten, wenn der Benutzer authentifiziert, aber nicht autorisiert ist. Dann müssen Sie das Attribut Authorize
erweitern und die Methode HandleUnauthorizedRequest
überschreiben.
Für ex.
public class CustomAuthorize: AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new HttpUnauthorizedResult();
}
else
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "AccessDenied" }));
}
}
}
Sie können die Variable HandleUnauthorizedRequest
je nach Bedarf überschreiben. Anschließend müssen Sie die Controller-Aktionen markieren, um das Attribut CustomAuthorize
anstelle des integrierten Attributs zu verwenden.
Ich mag die Antwort von Markus,
Ich möchte jedoch nicht alle meine Aktionsattribute ändern
von [Authorize] bis [CustomAuthorize]
Ich bearbeite die Funktion Login()
für AccountController
und überprüfen Sie Request.IsAuthenticated
vor der Showansicht
Ich denke, wenn der authentifizierte Benutzer zu /Account/Logon
geht,
Ich werde zu /Error/AccessDenied
umleiten.
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
if (Request.IsAuthenticated)
{
return RedirectToAction("AccessDenied", "Error");
}
ViewBag.ReturnUrl = returnUrl;
return View();
}
Platzieren Sie "/ account/logOn" anstelle von "~/account/logOn"
Ja, es ist richtig, wie Sie es in der web.config erwähnt haben
<forms loginUrl="~/Account/LogOn" timeout="2880" />
die Umleitung sucht nach Account-Controller und LogOn-Aktionsergebnis. Wenn Sie Ihre Seite umleiten möchten, wechseln Sie dort anstelle von Konto und Anmeldung
Da ich AuthorizeAttribute
nicht überschreiben wollte, habe ich Filter verwendet
public class RedirectFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!IsAuthorized(filterContext))
{
filterContext.Result =
new RedirectToRouteResult(new RouteValueDictionary(new {controller = "AccessDenied"}));
}
}
private bool IsAuthorized(ActionExecutingContext filterContext)
{
var descriptor = filterContext.ActionDescriptor;
var authorizeAttr = descriptor.GetCustomAttributes(typeof(AuthorizeAttribute), false).FirstOrDefault() as AuthorizeAttribute;
if (authorizeAttr != null)
{
if(!authorizeAttr.Users.Contains(filterContext.HttpContext.User.ToString()))
return false;
}
return true;
}
}