การอนุญาตแบบกำหนดเองใน Asp.net WebApi - อะไรเป็นปัญหา?


113

ฉันกำลังอ่านจากแหล่งข้อมูลหลายแห่ง (หนังสือและคำตอบ SO) เกี่ยวกับการอนุญาตใน WebApi

สมมติว่าฉันต้องการเพิ่มแอตทริบิวต์ที่กำหนดเองซึ่งอนุญาตให้เข้าถึงได้สำหรับผู้ใช้บางรายเท่านั้น:

กรณีที่ # 1

ฉันเคยเห็นวิธีการ ลบล้าง OnAuthorizationนี้ซึ่งกำหนดการตอบสนองหากมีบางอย่างผิดปกติ

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
  {
   if ( /*check if user OK or not*/)
   {
     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
   }
  }
}

กรณีที่ # 2

แต่ฉันก็เคยเห็นตัวอย่างที่คล้ายกันนี้ซึ่งแทนที่ OnAuthorizationด้วย แต่ด้วยการโทรไปที่base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}

จากนั้นตรวจสอบว่า HttpActionContext.Responseได้ตั้งค่าไว้หรือไม่ หากไม่ได้ตั้งค่าไว้แสดงว่าคำขอนั้นได้รับอนุญาตและผู้ใช้ก็โอเค

กรณีที่ # 3

แต่ฉันก็เคยเห็นวิธีการลบล้างนี้ด้วยIsAuthorized :

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 protected override bool IsAuthorized(HttpActionContext context)
  {
   if ( /*check if user OK or not*/)
   {
    return true;// or false
   }
  }
}

กรณีที่ # 4

จากนั้นฉันก็เห็นตัวอย่างที่คล้ายกัน แต่มีการเรียก base.IsAuthorized (บริบท):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

อีกหนึ่งสิ่ง

และในที่สุด Dominick ก็พูดที่นี่ :

คุณไม่ควรแทนที่ OnAuthorization เพราะคุณจะขาดการจัดการ [AllowAnonymous]

คำถาม

  • 1) ฉันควรใช้วิธีใด: IsAuthorizedหรือOnAuthorization? (หรือใช้เมื่อใด)

  • 2) เมื่อไหร่ที่ฉันควรโทรหาbase.IsAuthorized orbase OnAuthorization`?

  • 3) นี่เป็นวิธีที่พวกเขาสร้างขึ้นหรือไม่? ว่าถ้าการตอบสนองเป็นโมฆะทุกอย่างก็โอเค? (กรณี # 2)

NB

โปรดสังเกตว่าฉันใช้ (และต้องการใช้) เฉพาะAuthorizeAttributeที่สืบทอดมาแล้ว เท่านั้นAuthorizationFilterAttribute

ทำไม?

เป็นขั้นตอนแรกใน: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

ใส่คำอธิบายภาพที่นี่

อย่างไรก็ตามฉันขอผ่านการขยายแอตทริบิวต์ Authorize


สิ่งที่คุณต้องการเพื่อลบล้างแอตทริบิวต์ Authorize? กรณีใช้งานที่คุณต้องการบรรลุคืออะไร? หากคุณต้องการอนุญาตการเข้าถึงสำหรับผู้ใช้บางรายทำไมไม่ใช้แอตทริบิวต์ [Authorize (Users = "Admin")] เช่นนี้
Taiseer Joudeh

1
@TaiseerJoudeh ตัวอย่างเช่นพยายามให้สิทธิ์ผู้ใช้ระหว่าง 10:00 ถึง 12:00 น. (กำหนดค่าได้) คุณไม่สามารถทำได้ด้วยบทบาทธรรมดาและผู้รับมอบอำนาจ คุณต้องสร้างตรรกะของคุณเอง
Royi Namir

คำตอบ:


93

ฉันควรใช้วิธีใด: IsAuthorized หรือ OnAuthorization (หรือใช้เมื่อใด)

คุณจะขยายได้AuthorizationFilterAttributeหากตรรกะการอนุญาตของคุณไม่ขึ้นอยู่กับข้อมูลประจำตัวที่กำหนดและบทบาท AuthorizeAttributeสำหรับการอนุมัติที่เกี่ยวข้องกับผู้ใช้คุณจะขยายและการใช้งาน OnAuthorizationสำหรับกรณีอดีตคุณจะแทนที่ IsAuthorizedสำหรับกรณีหลังคุณจะแทนที่ ในขณะที่คุณจะได้เห็นจากซอร์สโค้ดของแอตทริบิวต์เหล่านี้มีการทำเครื่องหมายเสมือนจริงสำหรับคุณสามารถแทนที่ถ้าคุณได้รับจากOnAuthorization AuthorizationFilterAttributeบนมืออื่น ๆ ที่วิธีการทำเครื่องหมายเสมือนในIsAuthorized AuthorizeAttributeฉันเชื่อว่านี่เป็นตัวชี้ที่ดีสำหรับการใช้งานที่ตั้งใจไว้

ฉันควรเรียก base.IsAuthorized หรือ base OnAuthorization เมื่อใด

คำตอบสำหรับคำถามนี้อยู่ที่วิธีการทำงานของ OO โดยทั่วไป หากคุณลบล้างวิธีการคุณสามารถจัดเตรียมการนำไปใช้งานใหม่หรือกลับไปใช้อย่างสมบูรณ์ในการใช้งานโดยผู้ปกครองและปรับปรุงพฤติกรรม ตัวอย่างเช่นใช้กรณีของIsAuthorized(HttpActionContext). ลักษณะการทำงานของคลาสพื้นฐานคือการตรวจสอบผู้ใช้ / บทบาทกับสิ่งที่ระบุในตัวกรองเทียบกับเอกลักษณ์ที่สร้างขึ้น สมมติว่าคุณต้องการทำทุกอย่าง แต่นอกจากนี้คุณต้องการตรวจสอบอย่างอื่นอาจขึ้นอยู่กับส่วนหัวของคำขอหรือบางอย่าง ในกรณีนี้คุณสามารถระบุการลบล้างเช่นนี้ได้

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    bool isAuthroized = base.IsAuthorized(actionContext);
    // Here you look at the header and do your additional stuff based on actionContext
    // and store the result in isRequestHeaderOk
    // Then, you can combine the results
    // return isAuthorized && isRequestHeaderOk;
}

ฉันขอโทษ แต่ไม่เข้าใจ Q3 ของคุณ BTW ตัวกรองการอนุญาตมีมานานแล้วและผู้คนก็ใช้มันกับสิ่งต่างๆทุกประเภทและบางครั้งก็ไม่ถูกต้องเช่นกัน

อีกหนึ่งสิ่ง. และในที่สุดก็มีผู้ชายคนนี้ที่พูดว่า: คุณไม่ควรแทนที่ OnAuthorization เพราะคุณจะพลาดการจัดการ [AllowAnonymous]

ผู้ชายที่บอกว่านั่นคือเทพเจ้าแห่งการควบคุมการเข้าถึง - Dominick เห็นได้ชัดว่ามันจะถูกต้อง หากคุณดูการใช้งานOnAuthorization(คัดลอกด้านล่าง)

public override void OnAuthorization(HttpActionContext actionContext)
{
    if (actionContext == null)
    {
        throw Error.ArgumentNull("actionContext");
    }

    if (SkipAuthorization(actionContext))
    {
        return;
    }

    if (!IsAuthorized(actionContext))
    {
        HandleUnauthorizedRequest(actionContext);
    }
}

การเรียกไปที่SkipAuthorizationเป็นส่วนที่ทำให้มั่นใจได้ว่าAllowAnonymousมีการใช้ตัวกรองกล่าวคือการอนุญาตจะถูกข้ามไป หากคุณลบล้างวิธีนี้คุณจะสูญเสียพฤติกรรมนั้นไป ที่จริงถ้าคุณตัดสินใจที่จะยึดการอนุมัติของคุณกับผู้ใช้ / AuthorizeAttributeบทบาทที่จุดที่คุณจะได้ตัดสินใจที่จะเป็นผลมาจาก เหลือเพียงตัวเลือกที่ถูกต้องสำหรับคุณ ณ จุดนั้นเท่านั้นที่จะถูกแทนที่IsAuthorizedและไม่ใช่ตัวเลือกที่ถูกแทนที่แล้วOnAuthorizationแม้ว่าจะเป็นไปได้ในทางเทคนิค

PS ใน ASP.NET Web API มีตัวกรองอื่นที่เรียกว่าตัวกรองการพิสูจน์ตัวตน แนวคิดคือคุณใช้สิ่งนั้นสำหรับการพิสูจน์ตัวตนและตัวกรองการอนุญาตสำหรับการอนุญาตตามที่ชื่อระบุ อย่างไรก็ตามมีตัวอย่างมากมายที่ขอบเขตนี้เหลวไหล ตัวอย่างตัวกรองการตรวจสอบสิทธิ์จำนวนมากจะทำการตรวจสอบสิทธิ์บางประเภท ยังไงก็ตามถ้าคุณมีเวลาและความต้องการที่จะเข้าใจมากขึ้นอีกนิดจะดูที่ MSDN นี้บทความ คำเตือน: ฉันเขียนเอง


ขอบคุณอีกครั้ง แต่ถ้าฉันอ่านระหว่างบรรทัด IsAuthenticated จะถูกเรียกโดย OnAuthirization ดังนั้นทำไมไม่แทนที่ OnAuthorization และฐานการโทร OnAuthorization แล้วตรวจสอบการตอบสนองล่ะ
Royi Namir

คุณสามารถทำได้ถ้านั่นคือสิ่งที่คุณต้องการ
Badri

ในคำถามที่สามของฉันฉันหมายถึง: หลังจากเรียกใช้ฟังก์ชันพื้นฐาน - ฐานตัวอย่างเช่น OnAuthorization วิธีเดียวที่จะตรวจสอบว่าสำเร็จหรือไม่ - คือการตรวจสอบคุณสมบัติการตอบสนองหรือไม่, ps ตัวอย่างมาจากหนังสือของคุณ :-)
Royi Namir

ใช่โดยทั่วไปคุณมองหารหัสสถานะ 401 แต่ไม่เป็นโมฆะเท่าที่ฉันรู้ BTW ฉันจำไม่ได้ว่าเขียนเกี่ยวกับการลบล้างOnAuthorizationในหนังสือของฉัน ฉันแน่ใจว่าฉันไม่ได้เขียนเกี่ยวกับการตรวจสอบการตอบสนองสำหรับ null เพราะนี่เป็นครั้งแรกที่ฉันได้ยินเกี่ยวกับเรื่องนี้ :)
Badri

ใช่ฉันสับสนกับหนังสือเล่มอื่น ฉันกำลังอ่านหนังสือ 3 เล่มพร้อมกัน: ความปลอดภัย (ของคุณ), การปฏิบัติ (ของคุณ) และ webapi pro (Tugberk's, Zeitler, Ali) อย่างที่คุณเห็นพวกเขาทำที่นั่น: i.stack.imgur.com/LNGi4.jpg - พวกเขาเพิ่งตรวจสอบว่า null ดังนั้นฉันควรตรวจสอบ null หรือรหัสข้อผิดพลาดหรือไม่
Royi Namir

18

โอเคข้อเสนอแนะของฉันคือให้ทำสิ่งต่อไปนี้โดยสมมติว่าคุณใช้โทเค็นผู้ถือ OAuth เพื่อปกป้อง Web API ของคุณและคุณกำลังตั้งค่า allowTime เป็นการอ้างสิทธิ์สำหรับผู้ใช้เมื่อคุณออกโทเค็น คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการพิสูจน์ตัวตนโดยใช้โทเค็นได้ที่นี่

  1. สร้าง CustomAuthorizeAttribute ซึ่งมาจาก AuthorizationFilterAttribute
  2. แทนที่วิธีการOnAuthorizationAsyncและใช้โค้ดตัวอย่างด้านล่าง:

     public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
    {
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
    
            var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;
    
            if (!principal.Identity.IsAuthenticated)
            {
                return Task.FromResult<object>(null);
            }
    
            var userName = principal.FindFirst(ClaimTypes.Name).Value;
            var userAllowedTime = principal.FindFirst("userAllowedTime").Value;
    
            if (currentTime != userAllowedTime)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla");
                return Task.FromResult<object>(null);
            }
    
            //User is Authorized, complete execution
            return Task.FromResult<object>(null);
    
        }
    }
  3. ตอนนี้ในคอนโทรลเลอร์ของคุณคุณใช้แอตทริบิวต์ CustomAuthorize เพื่อปกป้องคอนโทรลเลอร์ของคุณโดยใช้ตรรกะการอนุญาตนี้

1
ขอบคุณ แต่ตอนนี้ฉันกำลังใช้AuthorizeAttributeซึ่งสืบทอดAuthorizationFilterAttributeและ - นอกจากนี้เพื่อการเรียนรู้ฉันถามเป็นพิเศษเกี่ยวกับวิธีที่ฉันควรใช้และเกี่ยวกับการตอบกลับมีเนื้อหาหรือไม่ ...
Royi Namir

3

ASP.NET v5 เปิดตัวระบบการอนุญาตใหม่ทั้งหมด สำหรับผู้ที่จะใช้. NET 5 ฉันขอแนะนำให้ย้ายเข้าสู่ Microsoft.AspNet.Authorization

มันค่อนข้างยุ่งเหยิงที่เกิดจากการเก็บรักษาทั้งสองอย่าง System.Web.Http.AuthorizeและSystem.Web.Mvc.Authorizeการใช้งานการตรวจสอบสิทธิ์รุ่นเก่าอื่น ๆ

มันมีนามธรรมที่ดีมากของประเภทการกระทำ (สร้างอ่านอัปเดตลบ) ทรัพยากรบทบาทการอ้างสิทธิ์มุมมองข้อกำหนดที่กำหนดเองและอนุญาตให้สร้างตัวจัดการที่กำหนดเองโดยรวมสิ่งที่กล่าวมาข้างต้น นอกจากนี้ตัวจัดการเหล่านี้ยังสามารถใช้ร่วมกันได้อีกด้วย

ในการให้สิทธิ์ ASP.NET v5 ตอนนี้มีบทบาทในการประกาศที่เรียบง่ายและรูปแบบตามนโยบายที่สมบูรณ์ยิ่งขึ้นซึ่งการอนุญาตจะแสดงในข้อกำหนดและตัวจัดการจะประเมินผู้ใช้ที่อ้างว่าขัดกับข้อกำหนด การตรวจสอบที่จำเป็นอาจเป็นไปตามนโยบายหรือนโยบายง่ายๆซึ่งประเมินทั้งข้อมูลประจำตัวของผู้ใช้และคุณสมบัติของทรัพยากรที่ผู้ใช้พยายามเข้าถึง


14
รู้ดี แต่ไม่ตอบคำถามเลย
Zero3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.