Ich habe einen Controller in ASP.NET MVC, den ich auf die Administratorrolle beschränkt habe:
[Authorize(Roles = "Admin")]
public class TestController : Controller
{
...
Wenn ein Benutzer, der nicht in der Administratorrolle ist, zu diesem Controller navigiert, wird er mit einem leeren Bildschirm begrüßt.
Ich möchte sie zu View umleiten, in dem steht, dass Sie in der Administratorrolle sein müssen, um auf diese Ressource zugreifen zu können.
Eine Möglichkeit, dies zu tun, besteht darin, jede Aktionsmethode in IsUserInRole () zu überprüfen und, falls nicht in der Rolle, diese Informationsansicht zurückzugeben. Allerdings müsste ich das in jede Aktion einfügen, die gegen das DRY-Prinzip verstößt und deren Wartung offensichtlich umständlich ist.
Sie können mit dem Overridable
HandleUnauthorizedRequest
in Ihrem Benutzer arbeitenAuthorizeAttribute
So was:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // Returns HTTP 401 by default - see HttpUnauthorizedResult.cs. filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary { { "action", "YourActionName" }, { "controller", "YourControllerName" }, { "parameterName", "YourParameterValue" } }); }
Sie können auch so etwas tun:
private class RedirectController : Controller { public ActionResult RedirectToSomewhere() { return RedirectToAction("Action", "Controller"); } }
Jetzt können Sie es in Ihrer
HandleUnauthorizedRequest
Methode folgendermaßen verwenden:filterContext.Result = (new RedirectController()).RedirectToSomewhere();
quelle
Der Code von "tvanfosson" gab mir "Fehler beim Ausführen der untergeordneten Anforderung". Ich habe die OnAuthorization folgendermaßen geändert:
public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); if (!_isAuthorized) { filterContext.Result = new HttpUnauthorizedResult(); } else if (filterContext.HttpContext.User.IsInRole("Administrator") || filterContext.HttpContext.User.IsInRole("User") || filterContext.HttpContext.User.IsInRole("Manager")) { // is authenticated and is in one of the roles SetCachePolicy(filterContext); } else { filterContext.Controller.TempData.Add("RedirectReason", "You are not authorized to access this page."); filterContext.Result = new RedirectResult("~/Error"); } }
Dies funktioniert gut und ich zeige die TempData auf der Fehlerseite. Vielen Dank an "tvanfosson" für das Code-Snippet. Ich verwende die Windows-Authentifizierung und _isAuthorized ist nichts anderes als HttpContext.User.Identity.IsAuthenticated ...
quelle
Ich hatte das gleiche Problem. Anstatt den MVC-Code herauszufinden, entschied ich mich für einen billigen Hack, der zu funktionieren scheint. In meiner Global.asax-Klasse:
member x.Application_EndRequest() = if x.Response.StatusCode = 401 then let redir = "?redirectUrl=" + Uri.EscapeDataString x.Request.Url.PathAndQuery if x.Request.Url.LocalPath.ToLowerInvariant().Contains("admin") then x.Response.Redirect("/Login/Admin/" + redir) else x.Response.Redirect("/Login/Login/" + redir)
quelle
Dieses Problem hat mich seit einigen Tagen verfolgt. Als ich die Antwort fand, die mit der obigen Antwort von tvanfosson positiv zusammenarbeitet, hielt ich es für sinnvoll, den Kernteil der Antwort hervorzuheben und einige verwandte Probleme anzusprechen.
Die Kernantwort lautet: süß und einfach:
filterContext.Result = new HttpUnauthorizedResult();
In meinem Fall erbe ich von einem Basis-Controller. In jedem Controller, der von diesem erbt, überschreibe ich OnAuthorize:
protected override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); YourAuth(filterContext); // do your own authorization logic here }
Das Problem war, dass ich in 'YourAuth' zwei Dinge ausprobiert habe, von denen ich dachte, dass sie nicht nur funktionieren, sondern auch die Anfrage sofort beenden würden. Nun, so funktioniert es nicht. Also zuerst die zwei Dinge, die NICHT unerwartet funktionieren:
filterContext.RequestContext.HttpContext.Response.Redirect("/Login"); // doesn't work! FormsAuthentication.RedirectToLoginPage(); // doesn't work!
Diese funktionieren nicht nur nicht, sie beenden auch die Anfrage nicht. Was bedeutet folgendes:
if (!success) { filterContext.Result = new HttpUnauthorizedResult(); } DoMoreStuffNowThatYouThinkYourAuthorized();
Nun, auch mit der richtigen Antwort oben geht der Logikfluss weiter! Sie werden weiterhin DoMoreStuff ... in OnAuthorize drücken. Denken Sie also daran (DoMore ... sollte daher in einem anderen sein).
Aber mit der richtigen Antwort, während der OnAuthorize-Logikfluss noch bis zum Ende andauert, erhalten Sie danach wirklich das, was Sie erwarten: eine Weiterleitung zu Ihrer Anmeldeseite (wenn Sie eine in Forms auth in Ihrer Webkonfiguration festgelegt haben).
Aber unerwartet funktioniert 1) Response.Redirect ("/ Login") nicht: Die Action-Methode wird weiterhin aufgerufen, und 2) FormsAuthentication.RedirectToLoginPage (); macht das gleiche: Die Action-Methode wird immer noch aufgerufen!
Was mir völlig falsch erscheint, insbesondere bei letzterem: Wer hätte gedacht, dass FormsAuthentication.RedirectToLoginPage die Anforderung nicht beendet, oder das Äquivalent darüber, was filterContext.Result = new HttpUnauthorizedResult () tut?
quelle
Sie sollten Ihr eigenes Authorize-Filter-Attribut erstellen.
Hier ist meins zum Lernen;)
Public Class RequiresRoleAttribute : Inherits ActionFilterAttribute Private _role As String Public Property Role() As String Get Return Me._role End Get Set(ByVal value As String) Me._role = value End Set End Property Public Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext) If Not String.IsNullOrEmpty(Me.Role) Then If Not filterContext.HttpContext.User.Identity.IsAuthenticated Then Dim redirectOnSuccess As String = filterContext.HttpContext.Request.Url.AbsolutePath Dim redirectUrl As String = String.Format("?ReturnUrl={0}", redirectOnSuccess) Dim loginUrl As String = FormsAuthentication.LoginUrl + redirectUrl filterContext.HttpContext.Response.Redirect(loginUrl, True) Else Dim hasAccess As Boolean = filterContext.HttpContext.User.IsInRole(Me.Role) If Not hasAccess Then Throw New UnauthorizedAccessException("You don't have access to this page. Only " & Me.Role & " can view this page.") End If End If Else Throw New InvalidOperationException("No Role Specified") End If End Sub End Class
quelle
filterContext.Result = new RedirectResult(loginUrl)
Hätte dies als Kommentar hinterlassen, aber ich brauche mehr Repräsentanten, trotzdem wollte ich Nicholas Peterson nur erwähnen, dass es vielleicht funktioniert hätte, das zweite Argument an den Redirect-Aufruf zu übergeben, um ihm zu sagen, dass die Antwort beendet werden soll. Nicht die anmutigste Art, damit umzugehen, aber es funktioniert tatsächlich.
Damit
filterContext.RequestContext.HttpContext.Response.Redirect("/Login", true);
anstatt
filterContext.RequestContext.HttpContext.Response.Redirect("/Login);
Das hätten Sie also in Ihrem Controller:
protected override void OnAuthorization(AuthorizationContext filterContext) { if(!User.IsInRole("Admin") { base.OnAuthorization(filterContext); filterContext.RequestContext.HttpContext.Response.Redirect("/Login", true); } }
quelle
Möglicherweise wird eine leere Seite angezeigt, wenn Sie Visual Studio unter einem Entwicklungsserver mit Windows-Authentifizierung ausführen ( vorheriges Thema) ).
Wenn Sie auf IIS bereitstellen, können Sie benutzerdefinierte Fehlerseiten für bestimmte Statuscodes konfigurieren, in diesem Fall 401. Fügen Sie unter system.webServer httpErrors hinzu:
<httpErrors> <remove statusCode="401" /> <error statusCode="401" path="/yourapp/error/unauthorized" responseMode="Redirect" /> </httpErrors>
Erstellen Sie dann die ErrorController.Unauthorized-Methode und die entsprechende benutzerdefinierte Ansicht.
quelle
Fügen Sie in Ihrer Datei Startup.Auth.cs die folgende Zeile hinzu:
LoginPath = new PathString("/Account/Login"),
Beispiel:
// Enable the application to use a cookie to store information for the signed in user // and to use a cookie to temporarily store information about a user logging in with a third party login provider // Configure the sign in cookie app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { // Enables the application to validate the security stamp when the user logs in. // This is a security feature which is used when you change a password or add an external login to your account. OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) } });
quelle