2014-02-27 3 views
7

Ich habe eine MVC-Website, in der Zugriff auf verschiedene Rollen basiert. Sobald sich ein Benutzer am System anmeldet, kann er die Navigation zu den Seiten sehen, für die er autorisiert ist. Einige Benutzer versuchen jedoch möglicherweise weiterhin, mithilfe einer direkten URL auf Seiten zuzugreifen. Wenn dies der Fall ist, leitet das System sie automatisch zur Anmeldeseite weiter. Statt der Login-Seite möchte ich sie in eine andere Ansicht umleiten (Unauthorized).Umleiten von nicht autorisierten Seitenzugriff in MVC auf benutzerdefinierte Ansicht

Web.Config hat den folgenden Eintrag:

<customErrors mode="On"> 
     <error statusCode="401" redirect="~/Home/Unauthorized" /> 
     <error statusCode="404" redirect="~/Home/PageNotFound" /> 
    </customErrors> 
    <authentication mode="Forms"> 
<forms name="Development" loginUrl="~/Account/Login" cookieless="UseCookies" timeout="120"></forms> 
    </authentication> 

ich auch diese Routen in Global.asax.cs registriert haben.

routes.MapRoute(
    name: "Unauthorized", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Unauthorized", id = UrlParameter.Optional } 
    ); 


routes.MapRoute(
    name: "PageNotFound", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "PageNotFound", id = UrlParameter.Optional } 
    ); 

Wird es genug sein?

Antwort

12

Mit Änderung folgenden es funktioniert

public class CustomAuthorize : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     //filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure 
      filterContext.Result = new RedirectResult("~/Home/Unauthorized"); 
    } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (this.AuthorizeCore(filterContext.HttpContext)) 
     { 
      base.OnAuthorization(filterContext); 
     } 
     else 
     { 
      this.HandleUnauthorizedRequest(filterContext); 
     } 
    } 

} 

Und dann an Controller oder Aktion Anwendung wie folgt:

[CustomAuthorize(Roles = "Admin")] 

Mit ich oben Ansatz müssen alle Controller/Aktionen zu überdenken und die autorisierten ändern Attribut! Auch einige Tests werden benötigt.

Ich bin immer noch nicht sicher, warum Web.Config Route funktioniert nicht wie in der MVC-Dokumentation erläutert wurde. Vielleicht hat sich etwas in MVC 4 geändert!

0

Ich glaube, Sie Ihr eigenes Autorisieren Filterattribut erstellen sollten, die Autorisieren

Filter des Standard erbt
public class CustomAuthorize: AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure 
    } 
} 
+1

Da andere Vorgehensweise nicht funktioniert, wähle ich diese Route. Vielen Dank! Ich werde immer noch versuchen herauszufinden, warum web.config nicht funktioniert hat. Wird jeden Fund hier veröffentlichen. Prost! – user2739418

+0

Haben Sie es gelöst? –

2

Wahrscheinlich besten Weg, dies zu handhaben ist, ein zusätzliches Aktionsfilter zu erstellen, das leitet den Benutzer auf den angegebenen Fehler Seite, wenn er nicht zur angegebenen Rolle gehört. Bei dieser Methode werden also beide Filter angewendet: [Autorisieren] (ohne Rollen), um vor nicht authentifizierten Benutzern zu schützen und sie auf die Anmeldeseite umzuleiten. Und Ihr benutzerdefiniertes Attribut mit den Rollen. Code ähnlich wie diese (nicht getestet):

public class RoleFilterAttribute : ActionFilterAttribute 
{ 
    public string Role { get; set; } 
    public override void OnActionExecuting(ActionExecutingContext ctx) 
    { 
     // Assume that we have user identity because Authorize is also 
     // applied 
     var user = ctx.HttpContext.User; 
     if (!user.IsInRole(Role)) 
     { 
      ctx.Result = new RedirectResult("url_needed_here"); 
     } 
    } 
} 

Nehmen sowohl [autorisieren] und [RoleFilter] auf die Aktionen ...

hoffe, das hilft!

+0

Eigenschaft "public string Role {get; set;}" Wie wird der Benutzer wissen, dass er zu bestimmten Rollen gehört? Wird es aber versuchen! – user2739418

+0

Hallo, die Eigenschaft ist zum Speichern der Rolle, die Sie überprüfen möchten. Wenn Sie also eine Methode nur für "Manager" schützen möchten, können Sie Folgendes verwenden: [RoleFilter (Role = "Manager")] bei Ihrer Aktion. In diesem Beispiel wird nur nach einer Rolle gesucht, aber die Erweiterung auf N-Rollen (d. H. Getrennt durch Kommata) ist trivial. Die Methode, die die Überprüfung wirklich durchführt, ist IsInRole. – eiximenis

14

Nach ein paar Recherchen denke ich, die einfachste Antwort auf dieses Problem ist nur benutzerdefinierte Autorisierung erstellen, sehr ähnlich zu der von jbbi (aber das hat nicht funktioniert, seit die "neue HttpUnauthorizedResult()" intern automatisch umgeleitet wird Login - zumindest in mvc 5 mit Identität)

public class CustomAuthorize : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      //if not logged, it will work as normal Authorize and redirect to the Login 
      base.HandleUnauthorizedRequest(filterContext); 

     } 
     else 
     { 
      //logged and wihout the role to access it - redirect to the custom controller action 
      filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "AccessDenied" })); 
     } 
    } 
} 

und die Nutzung ist das gleiche wie die Standard-Autorisieren:

[CustomAuthorize(Roles = "Administrator")] 

Dann, gerade die Dinge richtig zu tun, vergessen Sie nicht zu versenden der Http-Code der Fehlerseite. f. so in der Steuerung.

public ActionResult AccessDenied() 
{ 
    Response.StatusCode = 403; 
    return View(); 
} 

Es ist einfach, es funktioniert und sogar ich (.net mvc Rookie) verstehe dies.

Hinweis: Es funktioniert nicht das gleiche mit 401-Code - es wird immer die 401 übernehmen und intern umleiten es an die Anmeldung. Aber in meinem Fall ist per Definition der 403 auch passend.

+0

Ich habe vergessen, wie ich das diesmal gemacht habe. Oben sieht gut aus. Ich werde versuchen, es zu implementieren und zu sehen, ob es wie vorgesehen funktioniert. – user2739418

Verwandte Themen