ASP.NET MVC'de dinamik bir oturum açma URL'sine yeniden yönlendirme


96

Müşteriler için sayfalar barındıran çok kiracılı bir web sitesi oluşturuyorum. URL'nin ilk segmenti, aşağıdaki URL yönlendirme şeması kullanılarak Global.asax'ta tanımlanan istemciyi tanımlayan bir dize olacaktır:

"{client}/{controller}/{action}/{id}"

Bu, / foo / Home / Index gibi URL'lerde iyi çalışır.

Ancak, [Yetkilendir] özniteliğini kullanırken, aynı eşleme şemasını kullanan bir oturum açma sayfasına yeniden yönlendirmek istiyorum. Dolayısıyla, istemci foo ise, oturum açma sayfası web.config dosyasında tanımlanan sabit / Hesap / Oturum açma yönlendirmesi yerine / foo / Hesap / Oturum aç olacaktır.

MVC, 401 yetkisiz durumunu döndürmek için bir HttpUnauthorizedResult kullanır; bu, ASP.NET'in web.config içinde tanımlanan sayfaya yönlendirmesine neden olur.

Peki, ASP.NET oturum açma yeniden yönlendirme davranışını nasıl geçersiz kılacağını bilen var mı? Veya özel bir yetkilendirme özelliği oluşturarak MVC'de yeniden yönlendirme yapmak daha mı iyi olur?

DÜZENLEME - Cevap: .Net kaynağına biraz girdikten sonra, özel bir kimlik doğrulama özelliğinin en iyi çözüm olduğuna karar verdim:

public class ClientAuthorizeAttribute: AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        base.OnAuthorization( filterContext );

        if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "client", filterContext.RouteData.Values[ "client" ] },
                    { "controller", "Account" },
                    { "action", "Login" },
                    { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                });
        }
    }
}

2
yönlendirme ile neredeyse aynı şeyi yapıyor, bu yüzden buna ihtiyacım vardı! Teşekkürler!
Trevor de Koekkoek

Teşekkürler, benzer bir şeyin nasıl yapılacağını bulmaya çalışıyordum.
Şans

bana kendi uygulaması için fikir verdi, çok teşekkürler!
Alexander Beletsky

3
MVC 2 ve üstü kullanıyorsanız alan = null (veya doğru alana) ayarladığınızdan emin olun - yoksa ziyaret etmeye çalıştığınız sayfadan miras alınır
Simon_Weaver

Bunu MVC olmadan yapmanın bir yolu var mı?
DARKGuy

Yanıtlar:


30

Ben ana sorun, yerleşik ASP.NET FormsAuthentication sınıfının omzunda gidiyoruz olduğunu düşünüyorum (ve iyi bir neden yapmamalısın yoktur) çağrı gidiyor, günün sonunda bir şeyler FormsAuthentication.RedirectToLoginPage()oluyor ki yapılandırılmış bir URL'ye bakmak için. Şimdiye kadar yalnızca bir giriş URL'si var ve bu şekilde tasarladılar.

Benim problemim (muhtemelen bir Rube Goldberg uygulaması), tüm müşteriler tarafından paylaşılan kökteki tek bir giriş sayfasına, örneğin / account / login'e yönlendirilmesine izin vermek olacaktır. Bu giriş sayfası aslında hiçbir şey göstermez; ya ReturnUrl parametresini ya da oturumda aldığım bazı değerleri ya da istemciyi tanımlayan bir tanımlama bilgisini inceler ve bunu, belirli / müşteri / hesap / oturum açma sayfasına anında 302 yönlendirmesi göndermek için kullanır. Bu fazladan bir yönlendirme, ancak muhtemelen fark edilmez ve yerleşik yeniden yönlendirme mekanizmalarını kullanmanıza izin verir.

Diğer seçenek, açıklarken kendi özel niteliğinizi oluşturmak RedirectToLoginPage()ve FormsAuthenticationsınıfta yöntemi çağıran herhangi bir şeyden kaçınmaktır , çünkü onu kendi yeniden yönlendirme mantığınızla değiştireceksiniz. (Benzer bir sınıf yaratabilirsiniz.) Statik bir sınıf olduğu için, kendi alternatif arayüzünüzü enjekte edip sihirli bir şekilde mevcut [Authorize] özniteliğiyle çalışmasını sağlayabileceğiniz herhangi bir mekanizmanın farkında değilim. darbeler, ancak insanlar daha önce benzer şeyler yaptı .

Umarım yardımcı olur!


bu muhtemelen en güvenli yaklaşımdır. kendi [MyAuthorize] özelliğinizi oluşturmak tehlikelidir. yapınız insanların yerleşik [Yetkilendir] özniteliğini kullanmadığını doğrulamıyorsa, insanları (veya kendinizi) yanlış olanı
unutup

Bazı durumlarda, geçersiz kılmak faydalı olabilir Application_AuthenticateRequest(aşağıdaki cevabıma bakın).
turdus-merula

41

ASP.NET MVC'nin RTM sürümünde Cancel özelliği eksik. Bu kod ASP.NET MVC RTM ile çalışır:

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Resources;

namespace ePegasus.Web.ActionFilters
{
    public class CustomAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result = new RedirectToRouteResult(
                    new System.Web.Routing.RouteValueDictionary
                        {
                                { "langCode", filterContext.RouteData.Values[ "langCode" ] },
                                { "controller", "Account" },
                                { "action", "Login" },
                                { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                        });
            }
        }
    }
}

Düzenleme: Web.config'deki varsayılan form kimlik doğrulaması loginUrl'yi devre dışı bırakmak isteyebilirsiniz - birinin sizin özel bir özniteliğiniz olduğunu unutması ve yanlışlıkla yerleşik [Yetkilendir] özniteliğini kullanması durumunda.

Web.config'deki değeri değiştirin:

 <forms loginUrl="~/Account/ERROR" timeout="2880" />

Ardından, bir hatayı günlüğe kaydeden ve kullanıcıyı sahip olduğunuz en genel giriş sayfasına yönlendiren bir 'HATA' eylem yöntemi oluşturun.


2
MVC 2 ve üzeri kullanıyorsanız sözlüğe {alan, null} eklediğinizden emin olun (veya alanınız ne
denirse)

2

Bu soruna çözümüm özel bir ActionResultsınıftı:

    sealed public class RequiresLoginResult : ActionResult
    {
        override public void ExecuteResult (ControllerContext context)
        {
            var response = context.HttpContext.Response;

            var url = FormsAuthentication.LoginUrl;
            if (!string.IsNullOrWhiteSpace (url))
                url += "?returnUrl=" + HttpUtility.UrlEncode (ReturnUrl);

            response.Clear ();
            response.StatusCode = 302;
            response.RedirectLocation = url;
        }

        public RequiresLoginResult (string returnUrl = null)
        {
            ReturnUrl = returnUrl;
        }

        string ReturnUrl { get; set; }
    }

0

Biri kullanmaya karar verirse Yine de, yerleşik ASP.NET FormsAuthentication, tek overide edebilirsiniz Application_AuthenticateRequestiçinde Global.asax.csşöyle:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    string url = Request.RawUrl;

    if (url.Contains(("Account/Login"))
    {
        return;
    }

    if (Context.User == null)
    {
        // Your custom tenant-aware logic
        if (url.StartsWith("/foo"))
        {
            // Your custom login page.
            Response.Redirect("/foo/Account/Login");
            Response.End();
            return;
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.