2010-02-04 12 views
15

इसलिए जब आप उपयोगकर्ता लॉग इन करते हैं, तो लॉग इन लूप के बारे में एक और प्रश्न पढ़ रहा था, उस URL पर वापस लौटने के लिए सेट करें, जिसमें लॉग इन करने के बाद उनके पास पहुंच नहीं हो सकती है (यानी एक व्यवस्थापक पृष्ठ, और उपयोगकर्ता सामान्य के साथ लॉग इन करता है लेखा)।एएसपी.NET एमवीसी यह निर्धारित करने के लिए कि कोई उपयोगकर्ता यूआरएल तक पहुंच सकता है या नहीं?

वेबफॉर्म के तहत समाधान UrlAuthorizationModule.CheckUrlAccessForPrincipal विधि का उपयोग करना प्रतीत होता है। हालांकि यह प्राधिकरण विशेषता के साथ सुरक्षित कार्य विधियों पर जा रहे यूआरएल के लिए काम नहीं करता है। मैंने सोचा कि मैं काम कर सकता हूं कि यूआरएल किस तरह की ओर इशारा कर रहा था और मेरी समस्या को हल करने के लिए इसे प्रतिबिंबित कर रहा था - लेकिन मुझे लगता है कि मुझे यह जानकारी रूटिंग तालिका से कैसे प्राप्त होती है।

कोई भी इस के साथ काम किया है, या इसके लिए कोई समाधान है? अगर मैं सिर्फ एक यूआरएल से रूट जानकारी प्राप्त कर सकता हूं तो मुझे लगता है कि मैं बाकी काम कर सकता हूं, लेकिन अगर किसी के पास सामान्य समाधान है - यानी। कुछ छिपी हुई विधि एमवीसी के लिए पहले उल्लिखित एक के समान है, तो यह भी पूरी तरह से भयानक होगा।

मैं यह नहीं पूछ रहा हूं कि उपयोगकर्ता ने एक निर्दिष्ट नियंत्रक/एक्शन जोड़ी पर क्या आरोप लगाया है या नहीं। मुझे पहले और सबसे महत्वपूर्ण तरीके से यूआरएल के आधार पर रूटटेबल से कंट्रोलर/एक्शन जोड़ी कैसे प्राप्त करने की आवश्यकता है। सभी पृष्ठभूमि की कहानी का कारण यह है कि एमवीसी के लिए UrlAuthorizationModule.CheckUrlAccessForPrincipal के बराबर वास्तव में मौजूद है।

उत्तर

1

समस्या को हल करने की कोशिश कर रहे है:

मैं इस प्रकार यह करने के लिए एक विशेषता लिखा? ऐसा लगता है कि आप एक जटिल समाधान के मार्ग पर जा सकते हैं जो इसके बजाय एक साधारण समाधान का उपयोग कर सकता है।

कि उपयोगकर्ता लॉगिन, आप उपयोगकर्ताओं में गैर लॉग इन चाहते हैं एक पृष्ठ पर जाने के बाद पृष्ठ पर पहुंचने की अनुमति नहीं देता है, जबकि उपयोगकर्ताओं में लॉग इन एक अलग पृष्ठ पर जाने?

अगर ऐसी बात मैं सिर्फ इस तरह के परिदृश्यों के लिए एक और नियंत्रक बना सकते हैं और है कि नियंत्रक को अनुप्रेषित कहीं भी उपयोगकर्ता पहुँच नहीं है करने के लिए परीक्षा हो सकती है है। या यदि आप अपना खुद का बेस कंट्रोलर उपयोग कर रहे हैं तो मैं वहां कार्यक्षमता डालूंगा।

फिर नियंत्रक वांछित दृश्य पेश कर सकता था। उदाहरण के लिए यदि कोई गैर-लॉग इन उपयोगकर्ता किसी पृष्ठ तक पहुंचने का प्रयास करता है तो वे सामान्य त्रुटि पृष्ठ पर रीडायरेक्ट हो सकते हैं। यदि उपयोगकर्ता लॉग इन है, तो वे अधिकृत पृष्ठ पर रीडायरेक्ट हो सकते हैं।

यह रॉबर्ट के उत्तर के समान ही है।

यहाँ एक आधार नियंत्रक के लिए एक बुनियादी कंकाल है।

public BaseController: Controller 
{ 

... // Some code 

    public ActionResult DisplayErrorPage() 
    { 
     // Assumes you have a User object with a IsLoggedIn property 
     if (User.IsLoggedIn())  
      return View("NotAuthorized"); 

     // Redirect user to login page 
     return RedirectToAction("Logon", "Account"); 
    } 

} 

तब में मान लीजिए कि एक AdminController (कि BaseController से विरासत) कार्रवाई

public ActionResult HighlyRestrictedAction() 
{ 
    // Assumes there is a User object with a HasAccess property 
    if (User.HasAccess("HighlyRestrictedAction") == false) 
     return DisplayErrorPage(); 

    // At this point the user is logged in and has permissions 
    ... 
} 
+0

मैं इसे अभी स्वीकार करूँगा क्योंकि यह अब बल्ले से सबसे अच्छा समाधान प्रतीत होता है। मुझे यकीन नहीं है कि मैं वास्तव में इसका उपयोग करूंगा।मुझे वास्तव में इस तरह के तर्क को मेरे नियंत्रकों में एम्बेड करने का विचार पसंद नहीं है - मैं अतिरिक्त रीडायरेक्ट से बचना चाहता हूं। – kastermester

1

यह शायद विवादास्पद ध्वनि करने के लिए जा रहा है, लेकिन मैं प्रत्येक नियंत्रक विधि की शुरुआत में सुरक्षा की जांच, विधि के अंदर:

public class ProductController : Controller 
{ 
    IProductRepository _repository 

    public ActionResult Details(int id) 
    { 
     if(!_repository.UserHasAccess(id)) 
      return View("NotAuthorized"); 

     var item = _repository.GetProduct(id); 

     if (item == null) 
      return View("NotFound"); 

     return View(item); 
    } 
} 

कारण मैं [Authorize] विशेषताओं का उपयोग नहीं करते के लिए यह है कि आप है रनटाइम पर विशेषता के लिए आईडी या किसी अन्य पहचान जानकारी को पास नहीं कर सकता है।

+0

धन्यवाद, लेकिन मुझे यकीन नहीं है कि यह दृष्टिकोण मेरी मदद कैसे करेगा - टिप्पणियां जिन्हें मैंने jfar के लिए छोड़ा था। – kastermester

5

मैं पोर्ट और MvcSitemap से इस कोड को हैक कर लिया:

public static class SecurityTrimmingExtensions 
{ 

    /// <summary> 
    /// Returns true if a specific controller action exists and 
    /// the user has the ability to access it. 
    /// </summary> 
    /// <param name="htmlHelper"></param> 
    /// <param name="actionName"></param> 
    /// <param name="controllerName"></param> 
    /// <returns></returns> 
    public static bool HasActionPermission(this HtmlHelper htmlHelper, string actionName, string controllerName) 
    { 
     //if the controller name is empty the ASP.NET convention is: 
     //"we are linking to a different controller 
     ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) 
               ? htmlHelper.ViewContext.Controller 
               : GetControllerByName(htmlHelper, controllerName); 

     var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo); 

     var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType()); 

     var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName); 

     return ActionIsAuthorized(controllerContext, actionDescriptor); 
    } 


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     if (actionDescriptor == null) 
      return false; // action does not exist so say yes - should we authorise this?! 

     AuthorizationContext authContext = new AuthorizationContext(controllerContext); 

     // run each auth filter until on fails 
     // performance could be improved by some caching 
     foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters) 
     { 
      authFilter.OnAuthorization(authContext); 

      if (authContext.Result != null) 
       return false; 
     } 

     return true; 
    } 

    private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName) 
    { 
     // Instantiate the controller and call Execute 
     IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); 

     IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName); 

     if (controller == null) 
     { 
      throw new InvalidOperationException(

       String.Format(
        CultureInfo.CurrentUICulture, 
        "Controller factory {0} controller {1} returned null", 
        factory.GetType(), 
        controllerName)); 

     } 

     return (ControllerBase)controller; 
    } 

यह कुछ कैशिंग लेकिन मेरे मामले कि समय से पहले अनुकूलन था के लिए इस्तेमाल कर सकते हैं।

+0

मेरी समस्या यह है कि मेरे पास एक यूआरएल है, नियंत्रक नहीं है और एक क्रिया है। आपके द्वारा यहां लिखा गया कोड वह सामान है जो मुझे विश्वास है कि मैं खुद को पका सकता हूं - हालांकि इसे साझा करने के लिए धन्यवाद क्योंकि मुझे शायद इस तरह कुछ चाहिए। लेकिन सवाल यह है कि - मैं यूआरएल से रूटटेबल से निकाले गए नियंत्रक + एक्शन को कैसे प्राप्त करूं? कारण मैंने अन्य सामानों के बारे में बहुत कुछ लिखा था क्योंकि मुझे संदेह था कि वास्तव में यह सब मुझे 1 बजे बताने के लिए कहने का तरीका हो सकता है। – kastermester

+0

@kastermester: ऐसा करने के लिए, आपको नियंत्रक विधि निष्पादित होने से पहले अनुरोध को रोकना होगा। इसे कैसे करें इस पर विचारों के लिए, यहां देखें: http://stackoverflow.com/questions/2122459/how-malleable-are-the-conventions-in-asp-net-mvc/2122521#2122521 –

+0

बस मुझे जो चाहिए था। मैं इस के लिए उच्च और निम्न खोज रहा हूं। आपका बहुत बहुत धन्यवाद! –

0

सुरक्षा आवश्यकता के साथ अपने नियंत्रक विधियों को क्यों न दें।

public class RequiresRoleAttribute : ActionFilterAttribute 
     { 
      public string Role { get; set; } 

      public override void OnActionExecuting(ActionExecutingContext filterContext) 
      { 
       if (string.IsNullOrEmpty(Role)) 
       { 
        throw new InvalidOperationException("No role specified."); 
       } 


       if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
       { 
        filterContext.HttpContext.Response.Redirect(loginUrl, true); 
       } 
       else 
       { 
        bool isAuthorised = filterContext.HttpContext.User.IsInRole(this.Role); 

        << Complete Logic Here >> 



       } 
      }  
     } 
+0

मेरी समस्या यह है: कोई उपयोगकर्ता मेरे लॉगिन पेज पर जाता है। प्रविष्टि पर "वापसी" यूआरएल क्वेरी स्ट्रिंग में सेट और ले जाया जाता है। मान लीजिए कि एक सेकंड के लिए कि किसी भी तरह से यूआरएल साइट के एक व्यवस्थापक भाग को इंगित कर रहा है। एक सामान्य खाते के साथ उपयोगकर्ता लॉग इन करता है। अब इस तरह के कोड (जो मैं हूं) का उपयोग कर उपयोगकर्ता को लॉगिन पेज पर रीडायरेक्ट किया जाएगा - लेकिन वह पहले ही लॉग इन है! मैं बस डिफ़ॉल्ट पृष्ठ पर रीडायरेक्ट कर सकता था - लेकिन तब सभी वहां पहुंचेंगे - अनधिकृत लोग भी। लॉगिन के बाद रीडायरेक्ट करने से पहले मैं इसे सत्यापित करना चाहता हूं। – kastermester

1

अपने आवेदन में मैं AuthorizeAttribute से ली गई एक कस्टम फ़िल्टर, इसलिए किसी भी अनाधिकृत उपयोग बनाया है बस accessdenied पृष्ठ पर चला जाएगा । लिंक के लिए, मैं Html.ActionLink को एक कस्टम सहायक Html.SecureLink के साथ प्रतिस्थापित करता हूं। इस सहायक विस्तार में, मैं डेटाबेस के खिलाफ नियंत्रक/कार्रवाई के लिए इस उपयोगकर्ता की भूमिकाओं तक पहुंच की जांच करता हूं। वह/वह प्राधिकार हैं, तो वापस जाने के लिंक अन्यथा विशेष टिप्पणी के साथ लिंक पाठ लौट MVC 4 के लिए अद्यतन ऊपर

8

jfar के जवाब (छवि/रंग/js हो सकता है):

public static class SecurityCheck 
{ 
    public static bool ActionIsAuthorized(string actionName, string controllerName) 
    { 
     IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); 
     ControllerBase controller = factory.CreateController(HttpContext.Current.Request.RequestContext, controllerName) as ControllerBase; 
     var controllerContext = new ControllerContext(HttpContext.Current.Request.RequestContext, controller); 
     var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType()); 
     var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName); 
     AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor); 
     foreach (var authAttribute in actionDescriptor.GetFilterAttributes(true).Where(a => a is AuthorizeAttribute).Select(a => a as AuthorizeAttribute)) 
     { 
      authAttribute.OnAuthorization(authContext); 
      if (authContext.Result != null) 
       return false; 
     } 
     return true; 
    } 
} 
+0

या "foreach (var authArtribute in actionDescriptor.GetFilterAttributes (true) .OfType ())" - पैडेंट्री के लिए क्षमा मांगने के साथ। –

0

मैं सिर्फ कुछ खर्च @ jfar के समाधान को कार्यान्वित करने का समय (गैर-बहिष्कृत गेटफिल्टर() संस्करण के लिए इसे अपडेट करना), और फिर मुझे एहसास हुआ कि मैं इस पूरी चीज को छोड़ सकता हूं।

मेरे मामले में (और मुझे लगता है कि ज्यादातर मामलों में) मेरे पास साइट प्रमाणीकरण लागू करने के लिए एक कस्टम प्राधिकरण एट्रिब्यूट है जो बदले में मेरी पहुंच सेवा को वास्तविक पहुंच स्तर निर्धारण करने के लिए कॉल करता है।

@Html.MenuItem(@Url, "icon-whatever", "TargetController", "TargetAction") 

public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, UrlHelper url,string iconCss, string targetController, string targetAction) 
{ 
    var auth = IoC.Resolve<IClientAuthorizationService>().Authorize(targetController, targetAction); 
    if (auth == AccessLevel.None) 
     return MvcHtmlString.Create(""); 

* उपयोगकर्ता ग्राहक प्रमाणन सेवा के भीतर निर्धारित किया जाता है

public string GetUser() { 
    return HttpContext.Current.User.Identity.Name; 
} 

* भी कुछ जोड़ सकते हैं:

तो मेनू लिंक पैदा करने के लिए मेरी एचटीएमएल सहायक में, मैं प्रमाणन सेवा करने का अधिकार छोड़ दिया केवल पढ़ने के लिए उपयोग के लिए व्यवहार। यह अच्छा है क्योंकि मेरी ऑथ सेवा कैशिंग का ख्याल रखती है इसलिए मुझे प्रदर्शन के बारे में चिंता करने की ज़रूरत नहीं है।

संबंधित मुद्दे

 संबंधित मुद्दे