2015-01-29 6 views
6

मेरे पास एक नियंत्रक है जहां मैं निर्माता में एक सेवा इंटरफ़ेस इंजेक्शन दे रहा हूं। सेवा में इसके कन्स्ट्रक्टर में इंजेक्शन भी इंटरफेस है। आईओसी कंटेनर (एकता) को किसी दिए गए इंटरफ़ेस के लिए लौटने वाले वर्गों में से एक का निर्माण करते समय उपयोगकर्ता के बारे में जानकारी का उपयोग करने की आवश्यकता होती है।एएसपी.नेट एमवीसी नियंत्रक से पहले प्रमाणित

क्या हो रहा है, कि नियंत्रक से पहले [अधिकृत] विशेषता मूल्यांकन किया जाता है instantiated जा रहा है और उपयोगकर्ता को प्रमाणीकृत किया जाता है। यह एकता को निर्भरता इंजेक्शन करने के लिए मजबूर करता है और लॉग इन करने से पहले उपयोगकर्ता के बारे में जानकारी का उपयोग करता है। इनमें से कोई भी समस्या नहीं थी जब हम एकीकृत विंडोज प्रमाणीकरण का उपयोग कर रहे थे, लेकिन अब हम Azure AD से OpenID Connect का उपयोग कर रहे हैं और उपयोगकर्ता जानकारी isn ' जब तक वे लॉग इन नहीं करते हैं तब तक टी (नियंत्रक के बाद होता है)।

मैंने सुना

(अन्य पदों में) प्रमाणीकरण प्रक्रिया में पहले स्थानांतरित करने के लिए मेरी Owin स्टार्टअप वर्ग कॉन्फ़िगर करने के लिए एक तरीका है कि है, लेकिन मैं ऐसा करने के तरीके के बारे में कोई उदाहरण नहीं मिल सकता है। नियंत्रक को तत्काल होने से पहले मुझे होने वाले प्रमाणीकरण की आवश्यकता है।

यहाँ मैं क्या है की एक सरल उदाहरण है ...

नियंत्रक:

[Authorize] 
public class MyController : Controller 
{ 
    private readonly IMyService myService; 

    public MyController(IMyService myService) 
    { 
     this.myService = myService; 
    } 

    // ... 
} 

एकता विन्यास:

public class UnityBootstrap : IUnityBootstrap 
{ 
    public IUnityContainer Configure(IUnityContainer container) 
    { 
     // ... 

     return container 
      .RegisterType<ISomeClass, SomeClass>() 
      .RegisterType<IMyService>(new InjectionFactory(c => 
      { 
       // gather info about the user here 
       // e.g. 
       var currentUser = c.Resolve<IPrincipal>(); 
       var staff = c.Resolve<IStaffRepository>().GetBySamAccountName(currentUser.Identity.Name); 
       return new MyService(staff); 
      })); 
    } 
} 

Owin स्टार्टअप (Startup.Auth.cs):

public void ConfigureAuth(IAppBuilder app) 
{ 
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 

    app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

    app.UseOpenIdConnectAuthentication(
     new OpenIdConnectAuthenticationOptions 
     { 
      ClientId = this.clientID, 
      Authority = this.authority, 
      PostLogoutRedirectUri = this.postLogoutRedirectUri, 
      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       RedirectToIdentityProvider = context => 
       { 
        context.ProtocolMessage.DomainHint = this.domainHint; 
        return Task.FromResult(0); 
       }, 
       AuthorizationCodeReceived = context => 
       { 
        var code = context.Code; 

        var credential = new ClientCredential(this.clientID, this.appKey.Key); 
        var userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
        var authContext = new AuthenticationContext(this.authority, new NaiveSessionCache(userObjectID)); 
        var result = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, this.graphUrl); 
        AzureAdGraphAuthenticationHelper.Token = result.AccessToken; 
        return Task.FromResult(0); 
       } 
      } 
     }); 
} 
+0

मैं भी इस पर फिसल गया डि सामान में से किसी के बिना यद्यपि। उपयोगकर्ता नियंत्रक के कन्स्ट्रक्टर में उपयोगकर्ता की आवश्यकता है, और उपयोगकर्ता को 'प्राधिकृत एट्रिब्यूट' ने उपयोगकर्ता को स्थानांतरित करने से पहले कन्स्ट्रक्टर को देखकर आश्चर्यचकित किया। –

+1

इस तरह का एक स्पष्टीकरण क्यों है http://stackoverflow.com/a/4462767/10245 –

उत्तर

4

एफ मेरे मुद्दे को ऑनलाइन विशेष रूप से संबोधित करने में कुछ भी ढूंढने में असफल रहा, मैंने ASP.NET MVC 5 application lifecycle में खोदने का फैसला किया। मैंने पाया कि मैं एक कस्टम IControllerFactory (या DefaultControllerFactory से प्राप्त) बना सकता हूं जहां मैं CreateController विधि को परिभाषित कर सकता हूं।

CreateController के दौरान, मैं अगर उपयोगकर्ता को प्रमाणीकृत किया है देखने के लिए जाँच। यदि वे हैं, तो मैं बस डिफॉल्ट कंट्रोलर फैक्टरी को नियंत्रक बनाने की अनुमति देता हूं जैसा कि सामान्य रूप से होता है।

यदि उपयोगकर्ता प्रमाणीकृत नहीं है, तो मैं अनुरोधकर्ता के अनुरोध के लिए अनुरोध (नियंत्रक की कई परतों के साथ) (मेरे) सरल "ऑथ" नियंत्रक को अपरिवर्तित छोड़ दिया गया है।

प्रमाणीकरण नियंत्रक, कोई समस्या नहीं के साथ instantiated हो जाएगा जहां उसे कोई निर्भरता है। नोट: ऑथ नियंत्रक पर कभी भी कोई कार्रवाई निष्पादित नहीं की जाती है। एक बार ऑथ नियंत्रक बनने के बाद, वैश्विक प्राधिकरण एट्रिब्यूट में शामिल होता है और उपयोगकर्ता को प्रमाणित करने के लिए निर्देशित किया जाता है (ओपनआईडी कनेक्ट से Azure AD और ADFS) के माध्यम से।

में हस्ताक्षर करने के बाद, वे कुशलता में मूल RequestContext अभी भी साथ मेरे ऐप पर वापस पुनः निर्देशित कर रहे। CusomControllerFactory उपयोगकर्ता को प्रमाणीकृत के रूप में देखता है और अनुरोध किया गया नियंत्रक बनाया गया है।

यह विधि मेरे लिए बहुत अच्छा काम करती है क्योंकि मेरे नियंत्रकों की बड़ी निर्भरता श्रृंखला इंजेक्शन दी जा रही है (यानी नियंत्रक आईएसओएम सेवा पर निर्भर करता है जो कई आईसोम रिपोजिटरी, आईसोमहेल्पर, आईसोमिंगइल्स ... पर निर्भर करता है) और उपयोगकर्ता की कोई निर्भरता हल नहीं होती है में।

लॉग इन मैं अभी भी निश्चित रूप से अन्य (अधिक सुरुचिपूर्ण) कैसे प्राप्त करने के लिए मैं क्या मेरे मूल प्रश्न में पूछ रहा था पर विचार सुनने के लिए खुला रहा हूँ।


कस्टमकंट्रोलर फैक्टरी।सीएस

public class CustomControllerFactory : DefaultControllerFactory 
{ 
    public override IController CreateController(RequestContext requestContext, string controllerName) 
    { 
     var user = HttpContext.Current.User; 
     if (user.Identity.IsAuthenticated) 
     { 
      return base.CreateController(requestContext, controllerName); 
     } 

     var routeValues = requestContext.RouteData.Values; 
     routeValues["action"] = "PreAuth"; 
     return base.CreateController(requestContext, "Auth"); 
    } 
} 

Global.asax.cs

public class MvcApplication : HttpApplication 
{ 
    protected void Application_Start() 
    { 
     // ... 
     ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory)); 
    } 

    // ... 
} 

AuthController.cs

public class AuthController : Controller 
{ 
    public ActionResult PreAuth() 
    { 
     return null; 
    } 
} 
संबंधित मुद्दे