Soru ASP.NET MVC - Giriş sayfasında yetkisiz bir hata nasıl gösterilir?


ASP.NET MVC uygulamasında, çoğu denetleyiciyle süslendim

[Authorize(Roles="SomeGroup")]

Bir kullanıcı bir şeye erişme yetkisine sahip olmadığında, Hesap denetleyicimdeki Giriş eylemi olan "~ / Giriş" e gönderilir.

Bir kullanıcının uygun bir hatayı gösterebilmem için yetkili olmadığından giriş sayfasına ulaştığını nasıl belirleyebilirim?


44
2017-09-30 15:07


Menşei




Cevaplar:


İçin bakabilirsiniz ?ReturnUrl=  querystring değeri veya kendi yetki filtresini oluşturabilir ve TempData Nedeni belirtmek.

İşte hile yapacak basit bir özel filtre:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{

    // NOTE: This is not thread safe, it is much better to store this
    // value in HttpContext.Items.  See Ben Cull's answer below for an example.
    private bool _isAuthorized;

    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        _isAuthorized = base.AuthorizeCore(httpContext);
        return _isAuthorized;
    }

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

        if(!_isAuthorized)
        {
            filterContext.Controller.TempData.Add("RedirectReason", "Unauthorized");
        }
    }
}

Sonra görüşünüze göre, böyle bir şey yapabilirsiniz:

@if(TempData["RedirectReason"] == "Unauthorized")
{
    <b>You don't have permission to access that area</b>
}

(Her ne kadar bu sihirli dizelerden daha iyi bir yaklaşım önersem de, ama siz anlayın)


28
2017-09-30 15:21



Uygulaması kolay ve çalışır. Teşekkürler. - Ronnie Overby
Teşekkürler Ben, aynı şeyi benim tarafımda uyguluyorum ve çok iyi çalışıyorum! - Gabriel Mongeon
Bu cevap kabul edilir, ancak iş parçacığı güvenli değildir, lütfen daha fazla ayrıntı için aşağıya bakın. Lütfen iş parçacığı olmak için kodunuzu güncelleyin, birçok geliştirici diğer cevapları okuyamayabilir ve sizinkileri en iyi şekilde kullanabilir. - Serhiy Prysyazhnyy
Bu efekti bir yorum ekledi. - Ben Scheirman
Bu kodu projeme kopyaladığımda okudum ve okuduktan sonra okumaya başladım :) - EvAlex


GÜNCELLEME (Haziran 2015): @ daniel-lidström, bir ASP.NET MVC uygulamasında Response.Redirect kullanmamalısınız doğru bir şekilde işaret etti. Nedeniyle ilgili daha fazla bilgi için lütfen şu bağlantıya bakın: Response.Redirect ve ASP.NET MVC - Karıştırma.

GÜNCELLEME (Eylül 2014): HandleUnauthorizedRequest'in AuthorizeAttribute'a eklendiğinden emin değilim, ancak her iki şekilde de AuthorizeRedirect kodunu daha küçük ve daha basit bir şeye göre düzenleyebiliyorum.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeRedirect : AuthorizeAttribute
{
    public string RedirectUrl = "~/Error/Unauthorized";

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectResult(RedirectUrl);
        }
    }
}

Orijinal Cevap Aşağıda (hala tamamen işlevsel)

Bu cevabı burada bıraktım, çünkü size hala Yetkilendirme boru hattının nasıl çalıştığına dair bir fikir veriyor.

Hala buraya iniş yapan herkes için, Ben Scheirman'ın, kullanıcı giriş yapıp yetkilendirilmediğinde yetkisiz bir sayfaya otomatik olarak yönlendirme cevabını düzenledim. Yönlendirme yolunu RedirectUrl ad parametresini kullanarak değiştirebilirsiniz.

DÜZENLE: Çözümü tavsiye ederek iş parçacığı güvenliğini sağladım. Tarynn ve MSDN

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeRedirect : AuthorizeAttribute
{
    private const string IS_AUTHORIZED = "isAuthorized";

    public string RedirectUrl = "~/error/unauthorized";

    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        bool isAuthorized = base.AuthorizeCore(httpContext);

        httpContext.Items.Add(IS_AUTHORIZED, isAuthorized);

        return isAuthorized;
    }

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

        var isAuthorized = filterContext.HttpContext.Items[IS_AUTHORIZED] != null 
            ? Convert.ToBoolean(filterContext.HttpContext.Items[IS_AUTHORIZED]) 
            : false;

        if (!isAuthorized && filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl);
        }
    }
}

75
2018-03-08 23:15



MSDN'den: AuthorizeAttribute türetme AuthorizeAttribute sınıfından türetilirseniz, türetilen tür iş parçacığı güvenli olmalıdır. Bu nedenle, durumun tüm isteklere uygulanacağı anlamına gelmedikçe, durumu kendi türünün bir örneğinde (örneğin, bir örnek alanında) saklamayın. Bunun yerine, AuthorizeAttribute'ye geçirilen bağlam nesneleri aracılığıyla erişilebilen Items özelliğinde istek başına durumu depolayın. _is Yetkisiz bir örnek alan değil mi? - Tarynn
Mükemmel çalışıyor ama burada bir notu belirtmek istiyorum. 2 saatten fazla sürdüğü için, bazı hatalar uygulanır. - Filtreler gibi filtrelere eklemeyin. Ek (yeni AuthorizeRedirect ()); - Denetleyicide aşağıdakileri uygulayın: [AuthorizeRedirect (Roles = "Admins")] public class RoleController: Controller. [Authorize (Roles = "Admins") gibi bir uygulama yoktur. Public class RoleController: Controller - Grey Wolf
Sınıfta yönlendirme bağımlılığı yerine, onu değiştirdim. filterContext.RequestContext.HttpContext.AddError(new HttpException(403, "You have no power here...")); Hangi kullanmama izin ver customError web.config dosyasından Yine de aslında bir geri dönüş için bir yol olsaydı 403 onun yerine 302 gerçi. - MisterIsaak
@Dabbas Nope kesinlikle sadece eğer (). Doğrulandıysanız (giriş yaptıysanız) ancak yetkilendirilmediyseniz (izniniz varsa), "Giriş yaptığınızı biliyorum ve burada bulunmanıza izin verilmiyor" yazan bir sayfaya yönlendiriyorsunuz. - Ben Cull
filterContext.RequestContext.HttpContext.Response.Redirect (RedirectUrl) - Benim için bu gerçekten de yönlendirme gerçekleştirir de bir "System.Web.HttpException (0x80004005) atıyor: HTTP üstbilgileri gönderildikten sonra yeniden yönlendirilemiyor." kaputun altında. Bu önlenebilir ve eğer öyleyse nasıl? - ProNotion


Ben Cull yöntemi iyi çalışıyor, ancak System.Web.HTTP (Web API'sı tarafından kullanılan) ve System.Web.Mvc'de diğeri olmak üzere iki AuthorizeAttribute sınıfı olduğunu unutmayın. Ben'in yöntemi System.Web.Mvc sınıfını kullanır. Açıklık için, tam yolun kullanılmasını öneriyorum.

MVC yanında Web API kullanıyorsanız, iki filtre uygulamanız gerekir:

public class AuthorizeRedirectMVCAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectResult("~/Account/AccessDenied");
        }
    }
}

public class AuthorizeRedirectAPIAttribute : System.Web.Http.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);

        if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
        }
    }
}

Asp.net'in MVC kontrol cihazınızı bir API filtresiyle dekore etmenize izin vereceğini unutmayın - bu sadece beklediğiniz gibi çalışmayacaktır, bu yüzden özellik adlarınızı açık tutunuz.


5
2018-02-05 15:59





Bir denetleyiciniz varsa ve kodunuzda bir url olmasını istemiyorsanız, bu şekilde de yönlendirebilirsiniz. Tarayıcının adres çubuğunda URL'yi değiştirmeyecek, böylece kullanıcı yetkisiz bir sayfa için URL'yi asla görmeyecektir. Bu, MVC 3'te yazılmıştır. Bu yöntem, bunları bir giriş sayfasına yönlendirmek istiyorsanız veya yetkilendirilmediklerini söylemek için bir sayfaya yönlendirmek istiyorsanız da çalışır. Programda, bazı kullanıcıların haklarına sahip olmadıkları, ancak giriş yaptıkları bölümler vardı, bu yüzden kullandım.

public class AuthorizedRedirect : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool isAuthorized = base.AuthorizeCore(httpContext);
        return isAuthorized;
    }
protect override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.RequestContext.RouteData.Values["controller"] = "error";
    filterContext.Result = new ViewResult { ViewName = "unauthorized" };
}

4
2017-09-26 18:58



İletiyi Paylaşılan Görünüm'de göstermek için başka bir varyasyon olarak, ör. var vr = new ViewResult(); vr.ViewName = "Info"; vr.ViewBag.Message = "You are unauthorized for this page; contact us. "; filterContext.Result = vr; - subsci


FormsAuthentication ayarlarını kullanan daha da basit bir sürüm. Sözleşme ile aşina olmayanlar için, Contract.Requires bir .NET 4 ekidir. Artıları ve eksilerini kullanma Kod Sözleşmeleri.

public class RequiresAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        Contract.Requires(filterContext != null);

        HttpContextBase context = filterContext.RequestContext.HttpContext;

        if (context.User.Identity.IsAuthenticated)
        {
            // user does not possess the required role permission
            string url = context.GetCustomErrorUrl(401);
            context.Response.Redirect(url);
        }
        else
        {

            // redirect the user to the login page
            string extraQueryString  = context.Request.RawUrl;
            FormsAuthentication.RedirectToLoginPage(extraQueryString);
        }
    }
}

2
2017-09-27 00:21





Bir denetleyiciniz olmasa bile divide_byzero'nun yanıtından daha ileri gidersiniz, yönlendirmeyi değiştirmek için yine de HandleUnauthorizedRequest'i kullanabilirsiniz.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthoriseRedirect : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.Redirect("UrlToRedirectTo");
        }
    }

MVC'ye daha uzun bir zaman dilimi içinde dönüştüreceğiniz eski bir web formları siteniz varsa, kullanışlı olur!


1
2017-11-18 06:35





Brian Vander Plaats'ın yayınladığı şeyi sevdim, az sayıda gelişme ekledim:

/// <summary>
/// Authorize or redirect to an unauthorized MVC action if the user does not have the required roles
/// (an unauthenticated user will be redirected to the defualt sign in action)
/// <para>Decorate an action or a controller like this [AuthorizeAndRedirect(Roles = "RoleName")]</para>
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AuthorizeOrRedirectAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "Unauthorized");
            filterContext.Result = new RedirectToRouteResult(routeData.Values);
        }
    }
}

/// <summary>
/// Authorize or redirect to an unauthorized API action if the user does not have the required roles
/// (an unauthenticated user will be redirected to the defualt sign in action)
/// <para>Decorate an action or a controller like this [AuthorizeAndRedirect(Roles = "RoleName")]</para>
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AuthorizeOrRedirectApiFilterAttribute : System.Web.Http.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);

        if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }
}

0
2018-04-07 20:07