2014-09-03 16 views
12

Tôi không hiểu mục đích/sự khác biệt của OnAuthentication và OnAuthenticationChallenge ngoài OnAuthentication chạy trước khi một hành động thực hiện và OnAuthenticationChallenge chạy sau khi một hành động thực hiện nhưng trước khi kết quả hành động được xử lý.Thực hiện MVC 5 IAuthenticationFilter

Dường như một trong hai cách đó (OnAuthentication hoặc OnAuthenticationChallenge) có thể thực hiện tất cả những gì cần thiết để xác thực. Tại sao cần cho 2 phương pháp?

Sự hiểu biết của tôi là OnAuthentication là nơi chúng tôi đặt logic xác thực (hoặc logic này nên trong phương thức hành động thực tế?), Kết nối với lưu trữ dữ liệu và kiểm tra tài khoản người dùng. OnAuthenticationChallenge là nơi chúng tôi chuyển hướng đến trang đăng nhập nếu không được xác thực. Điều này có đúng không? Tại sao tôi không thể chuyển hướng trên OnAuthentication và không triển khai OnAuthenticationChallenge. Tôi biết có điều gì đó tôi đang thiếu; ai đó có thể giải thích cho tôi?

Phương pháp hay nhất để lưu trữ người dùng được xác thực để các yêu cầu thành công sẽ không phải kết nối với db để kiểm tra lại cho người dùng là gì?

Hãy nhớ rằng tôi mới sử dụng ASP.NET MVC.

Trả lời

22

Những phương pháp này thực sự dành cho các mục đích khác nhau:

  • IAuthenticationFilter.OnAuthentication nên được sử dụng để thiết lập hiệu trưởng, hiệu trưởng là đối tượng xác định người sử dụng.

    Bạn cũng có thể đặt kết quả theo phương pháp này như là HttpUnauthorisedResult (điều này sẽ giúp bạn tiết kiệm được từ việc thực hiện bộ lọc ủy quyền bổ sung). Trong khi điều này là có thể, tôi thích sự tách biệt mối quan tâm giữa các bộ lọc khác nhau.

  • IAuthenticationFilter.OnAuthenticationChallenge được sử dụng để thêm "thách thức" vào kết quả trước khi trả lại cho người dùng.

    • Điều này luôn được thực hiện ngay trước khi kết quả được trả lại cho người dùng, có nghĩa là nó có thể được thực hiện tại các điểm khác nhau của đường ống trên các yêu cầu khác nhau. Xem phần giải thích của ControllerActionInvoker.InvokeAction bên dưới.

    • Sử dụng phương pháp này cho mục đích "ủy quyền" (như kiểm tra xem người dùng đã đăng nhập hay trong một vai trò nhất định) có thể là một ý tưởng tồi vì nó có thể được thực thi SAU KHI mã tác vụ điều khiển, vì vậy bạn có thể đã thay đổi điều gì đó trong db trước khi điều này được thực hiện!

    • Ý tưởng là phương pháp này có thể được sử dụng để đóng góp cho kết quả, thay vì thực hiện kiểm tra ủy quyền quan trọng. Ví dụ: bạn có thể sử dụng nó để chuyển đổi một HttpUnauthorisedResult thành chuyển hướng đến các trang đăng nhập khác nhau dựa trên một số logic. Hoặc bạn có thể giữ một số thay đổi của người dùng, chuyển hướng anh ta đến một trang khác, nơi bạn có thể yêu cầu xác nhận/thông tin bổ sung và tùy thuộc vào câu trả lời cuối cùng hoặc loại bỏ những thay đổi đó.

  • IAuthorizationFilter.OnAuthorization vẫn nên được sử dụng để thực hiện kiểm tra xác thực, như kiểm tra nếu người dùng đang đăng nhập hoặc thuộc về một vai trò nhất định.

Bạn có thể có ý tưởng tốt hơn nếu bạn kiểm tra mã nguồn cho ControllerActionInvoker.InvokeAction.Điều sau sẽ xảy ra khi thực hiện một hành động:

  1. IAuthenticationFilter.OnAuthentication được gọi cho mỗi bộ lọc xác thực. Nếu hiệu trưởng được cập nhật trong AuthenticationContext, thì cả hai context.HttpContext.UserThread.CurrentPrincipal đều được cập nhật.

  2. Nếu bất kỳ bộ lọc xác thực nào thiết lập kết quả, ví dụ thiết lập kết quả 404 thì OnAuthenticationChallenge được gọi cho mọi bộ lọc xác thực, cho phép thay đổi kết quả trước khi được trả về. (Ví dụ, bạn có thể chuyển đổi nó thành một chuyển hướng để đăng nhập). Sau những thử thách, kết quả được trả về mà không cần chuyển sang bước 3.

  3. Nếu không có bộ lọc xác thực nào thiết lập kết quả thì cứ IAuthorizationFilter phương thức OnAuthorization của nó được thực thi.

  4. Như ở bước 2, nếu bất kỳ bộ lọc ủy quyền nào thiết lập kết quả, ví dụ thiết lập kết quả 404, thì OnAuthenticationChallenge được gọi cho mọi bộ lọc xác thực. Sau những thử thách, kết quả được trả về mà không tiến tới bước 3.

  5. Nếu không ai trong số các bộ lọc cho phép thiết lập một kết quả, sau đó nó sẽ tiến hành thực hiện các hành động (Có tính đến xác nhận yêu cầu tài khoản và bất kỳ bộ lọc hành động)

  6. Sau hành động được thực hiện và trước khi kết quả được trả về, OnAuthenticationChallenge được gọi là cho mỗi bộ lọc xác thực

tôi đã sao chép mã hiện tại của ControllerActionInvoker.InvokeAction đây như là một tài liệu tham khảo, nhưng bạn có thể sử dụng liên kết ở trên để xem phiên bản mới nhất :

public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) 
{ 
    if (controllerContext == null) 
    { 
     throw new ArgumentNullException("controllerContext"); 
    } 

    Contract.Assert(controllerContext.RouteData != null); 
    if (String.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch()) 
    { 
     throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName"); 
    } 

    ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext); 
    ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName); 

    if (actionDescriptor != null) 
    { 
     FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor); 

     try 
     { 
      AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor); 

      if (authenticationContext.Result != null) 
      { 
       // An authentication filter signaled that we should short-circuit the request. Let all 
       // authentication filters contribute to an action result (to combine authentication 
       // challenges). Then, run this action result. 
       AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
        controllerContext, filterInfo.AuthenticationFilters, actionDescriptor, 
        authenticationContext.Result); 
       InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result); 
      } 
      else 
      { 
       AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor); 
       if (authorizationContext.Result != null) 
       { 
        // An authorization filter signaled that we should short-circuit the request. Let all 
        // authentication filters contribute to an action result (to combine authentication 
        // challenges). Then, run this action result. 
        AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
         controllerContext, filterInfo.AuthenticationFilters, actionDescriptor, 
         authorizationContext.Result); 
        InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result); 
       } 
       else 
       { 
        if (controllerContext.Controller.ValidateRequest) 
        { 
         ValidateRequest(controllerContext); 
        } 

        IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor); 
        ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters); 

        // The action succeeded. Let all authentication filters contribute to an action result (to 
        // combine authentication challenges; some authentication filters need to do negotiation 
        // even on a successful result). Then, run this action result. 
        AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
         controllerContext, filterInfo.AuthenticationFilters, actionDescriptor, 
         postActionContext.Result); 
        InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, 
         challengeContext.Result ?? postActionContext.Result); 
       } 
      } 
     } 
     catch (ThreadAbortException) 
     { 
      // This type of exception occurs as a result of Response.Redirect(), but we special-case so that 
      // the filters don't see this as an error. 
      throw; 
     } 
     catch (Exception ex) 
     { 
      // something blew up, so execute the exception filters 
      ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex); 
      if (!exceptionContext.ExceptionHandled) 
      { 
       throw; 
      } 
      InvokeActionResult(controllerContext, exceptionContext.Result); 
     } 

     return true; 
    } 

    // notify controller that no method matched 
    return false; 
} 

Vì không nhấn db trên mọi yêu cầu khi đặt hiệu trưởng, bạn có thể sử dụng một số loại bộ nhớ cache phía máy chủ.

+0

Cảm ơn bạn đã trả lời. Vì vậy, nếu tôi hiểu chính xác, thiết lập hiệu trưởng được thực hiện trên OnAuthentication. Nhưng, đây có phải là nơi tôi kiểm tra kho dữ liệu cho người dùng không? Ngoài ra, trong số 2 "Nếu bất kỳ bộ lọc xác thực nào thiết lập kết quả, ví dụ thiết lập kết quả 404, thì OnAuthenticationChallenge được gọi cho mọi bộ lọc xác thực". Ý bạn là gì? Khi tôi thêm một breakpoint, nó luôn luôn chạy OnAuthenticationChallenge cho dù tôi đặt một kết quả hay không (tôi thậm chí đã cố gắng thiết lập kết quả để null). –

+0

Suy nghĩ, tôi dường như không thể thấy lý do tại sao sử dụng OnAuthenticationChallenge. Tôi đang suy nghĩ một cái gì đó như OnAuthentication, xác thực người dùng, nếu không được xác thực, chuyển hướng để đăng nhập thông qua kết quả ngữ cảnh, khác tiếp tục. Điều này tất cả có thể được thực hiện trong OnAuthentication. Bạn có thể cung cấp một ví dụ thực tế tại sao/khi tôi nên sử dụng OnAuthenticationChallenge? –

+2

Trong OnAuthentication bạn có thể đặt kết quả thành 'HttpUnauthorisedResult'. Sau đó, OnAuthenticationChallenge, bạn có thể ghi đè lên kết quả đó và trả về một 'RedirectResult' cho các trang khác nhau dựa trên một số logic. Vì logic này nằm trong OnAuthenticationChallenge, nó cũng sẽ được áp dụng nếu 'HttpUnauthorisedResult' được trả về trực tiếp từ một hành động điều khiển, từ một bộ lọc ủy quyền hoặc từ bất kỳ bộ lọc nào khác. –

Các vấn đề liên quan