การตรวจสอบผู้ใช้ใน ASP.NET Web API


150

หัวข้อนี้ทำให้ฉันสับสนอย่างเหลือเชื่อ ฉันเป็นมือใหม่ในแอพ HTTP แต่ต้องพัฒนาไคลเอนต์ iPhone ที่ใช้ข้อมูล JSON จากที่อื่น ฉันเลือก Web API จาก MS เพราะมันดูง่ายพอ แต่เมื่อพูดถึงการพิสูจน์ตัวตนผู้ใช้สิ่งต่างๆก็ค่อนข้างน่าผิดหวัง

ฉันประหลาดใจที่ฉันไม่สามารถหาตัวอย่างที่ชัดเจนเกี่ยวกับวิธีการรับรองความถูกต้องของผู้ใช้จากหน้าจอเข้าสู่ระบบจนถึงการใช้Authorizeแอตทริบิวต์เหนือApiControllerวิธีการของฉันหลังจากใช้ Google เป็นเวลาหลายชั่วโมง

นี่ไม่ใช่คำถาม แต่เป็นตัวอย่างของวิธีการทำเช่นนี้อย่างแน่นอน ฉันได้ดูหน้าต่อไปนี้:

แม้ว่าสิ่งเหล่านี้จะอธิบายวิธีจัดการกับคำขอที่ไม่ได้รับอนุญาต แต่สิ่งเหล่านี้ก็ไม่ได้แสดงให้เห็นอย่างชัดเจนว่าเป็นLoginControllerสิ่งที่ต้องการขอข้อมูลประจำตัวผู้ใช้และตรวจสอบความถูกต้อง

ทุกคนยินดีที่จะเขียนตัวอย่างง่ายๆที่ดีหรือชี้ฉันในทิศทางที่ถูกต้องโปรด?

ขอบคุณ


1
ฉันได้ตอบคำถามประเภทเดียวกันนี้: stackoverflow.com/questions/11775594/ …
cuongle

สำหรับ Web Api ที่มี asp.net คุณสามารถใช้คุกกี้และโมดูลการตรวจสอบสิทธิ์แบบฟอร์มเช่นเดียวกับแอป mvc (ถ้าคุณต้องการ) ดังนั้นในรหัสเว็บ API ของคุณคุณสามารถตรวจสอบเงินต้นเพื่อดูว่าผู้ใช้ลงชื่อเข้าใช้หรือไม่ (เช่นเดิม)
Elliot

ดูคำตอบของฉันสำหรับstackoverflow.com/questions/11775594/…
Varun Chatterji

ฉันขอแนะนำให้คนจำนวนมากอ่านบทความasp.net/web-api/overview/security/…
ยองแจ

คำตอบ:


176

ฉันประหลาดใจที่ฉันไม่สามารถหาตัวอย่างที่ชัดเจนของวิธีการรับรองความถูกต้องของผู้ใช้จากหน้าจอเข้าสู่ระบบจนถึงการใช้แอตทริบิวต์อนุญาตเหนือวิธี ApiController ของฉันหลังจาก Googling หลายชั่วโมง

นั่นเป็นเพราะคุณเริ่มสับสนกับแนวคิดสองข้อนี้:

  • การรับรองความถูกต้องเป็นกลไกที่ระบบสามารถระบุผู้ใช้ของตนได้อย่างปลอดภัย ระบบรับรองความถูกต้องให้คำตอบสำหรับคำถาม:

    • ใครคือผู้ใช้?
    • เป็นผู้ใช้จริง ๆ ที่เขา / เธอหมายถึงตัวเองเป็น
  • การอนุญาตเป็นกลไกที่ระบบจะกำหนดระดับการเข้าถึงของผู้ใช้ที่ได้รับการรับรองความถูกต้องโดยเฉพาะควรมีการรักษาความปลอดภัยทรัพยากรที่ควบคุมโดยระบบ ตัวอย่างเช่นระบบการจัดการฐานข้อมูลอาจได้รับการออกแบบเพื่อให้บุคคลที่ระบุบางอย่างมีความสามารถในการดึงข้อมูลจากฐานข้อมูล แต่ไม่สามารถเปลี่ยนข้อมูลที่เก็บไว้ในฐานข้อมูลในขณะที่ให้บุคคลอื่นสามารถเปลี่ยนข้อมูลได้ ระบบอนุญาตให้คำตอบสำหรับคำถาม:

    • user X ได้รับอนุญาตให้เข้าถึงทรัพยากร R หรือไม่
    • user X ได้รับอนุญาตให้ดำเนินการ P หรือไม่
    • user X ได้รับอนุญาตให้ดำเนินการ P บนทรัพยากร R หรือไม่

Authorizeแอตทริบิวต์ใน MVC จะใช้ในการใช้กฎการเข้าถึงตัวอย่างเช่น:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }

กฎข้างต้นจะอนุญาตเฉพาะผู้ใช้ในบทบาทผู้ดูแลระบบและผู้ใช้ระดับสูงเท่านั้นในการเข้าถึงวิธีการ

กฎเหล่านี้ยังสามารถตั้งค่าในไฟล์ web.config โดยใช้locationองค์ประกอบ ตัวอย่าง:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

อย่างไรก็ตามก่อนที่กฎการให้สิทธิ์เหล่านั้นจะถูกดำเนินการที่คุณจะต้องมีการรับรองความถูกต้องไปยังเว็บไซต์ปัจจุบัน

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

จากที่นี่เราสามารถแยกปัญหาออกเป็นสองส่วน:

  • รับรองความถูกต้องผู้ใช้เมื่อใช้บริการ Web API ภายในเว็บแอปพลิเคชันเดียวกัน

    นี่จะเป็นวิธีที่ง่ายที่สุดเพราะคุณจะต้องใช้การตรวจสอบความถูกต้องใน ASP.Net

    นี่คือตัวอย่างง่ายๆ:

    Web.config

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>

    ผู้ใช้จะถูกเปลี่ยนเส้นทางไปยังเส้นทางบัญชี / การเข้าสู่ระบบที่นั่นคุณจะทำการควบคุมแบบกำหนดเองเพื่อขอข้อมูลประจำตัวผู้ใช้จากนั้นคุณจะตั้งค่าคุกกี้การรับรองความถูกต้องโดยใช้:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
  • การพิสูจน์ตัวตนข้ามแพลตฟอร์ม

    กรณีนี้จะเกิดขึ้นเมื่อคุณเปิดเผยบริการ Web API ภายในแอปพลิเคชันเว็บเท่านั้นดังนั้นคุณจะมีไคลเอนต์อื่นที่ใช้บริการลูกค้าอาจเป็นแอปพลิเคชันเว็บอื่นหรือแอปพลิเคชัน. Net (Win Forms, WPF, คอนโซล, บริการ Windows) ฯลฯ )

    ตัวอย่างเช่นสมมติว่าคุณจะใช้บริการ Web API จากเว็บแอปพลิเคชันอื่นในโดเมนเครือข่ายเดียวกัน (ภายในอินทราเน็ต) ในกรณีนี้คุณสามารถใช้การรับรองความถูกต้อง Windows ที่ ASP.Net จัดหาให้

    <authentication mode="Windows" />

    หากบริการของคุณปรากฏบนอินเทอร์เน็ตคุณจะต้องส่งโทเค็นที่ผ่านการตรวจสอบแล้วไปยังบริการ Web API แต่ละบริการ

    สำหรับข้อมูลเพิ่มเติมนำของขวัญไปที่บทความต่อไปนี้:


3
ว้าว! นั่นคือสิ่งที่ฉันเรียกว่าคำตอบ ดังนั้นเพื่อสรุป ฉันวางแผนที่จะทำสิ่งต่อไปนี้: 1. สร้างบัญชีคอนโทรลเลอร์ด้วยวิธีการเข้าสู่ระบบที่ได้รับชื่อผู้ใช้และรหัสผ่านบน HTTPS และส่งกลับผลลัพธ์การเข้าสู่ระบบและโทเค็น 2. ลูกค้าจัดเก็บโทเค็นและส่งเป็นส่วนหัว (ไม่มี HTTPS อีกต่อไป) ในคำขอที่ได้รับการตรวจสอบความถูกต้องโดยเว็บเซิร์ฟเวอร์ นั่นเป็นแนวทางที่ดีหรือไม่? ดังนั้นข้อสงสัยสุดท้ายของฉันคือวิธีควบคุมการปลอมแปลงและการหมดอายุโทเค็น เป็นไปได้ไหม
Luis Aguilar

6
@Jupaol ฉันคิดว่าฉันพูดกับนักพัฒนาเว็บ API หลายคนฉันไม่สามารถใช้การรับรองความถูกต้องของฟอร์มได้เนื่องจากฉันไม่มีเว็บไซต์และลูกค้าไม่ได้ใช้เบราว์เซอร์และฉันไม่สามารถใช้การรับรองความถูกต้องแบบรวมเพราะผู้ใช้สามารถอยู่ที่ไหนก็ได้ในโลก ดังนั้น Web API) ดังนั้นฉันจะใช้อะไร
markmnl

21
ฉันไม่เข้าใจว่าทำไมคำตอบนี้ได้รับ upvote มากมาย มันไม่เกี่ยวกับ ASP.NET Web API แต่เกี่ยวกับ ASP.NET MVC
Bastien Vandamme

3
ผมอยากจะย้ำความคิดเห็น B413 และชี้ให้เห็นว่าคำถามนี้โดยเฉพาะขอเว็บ API
Julien

6
นี่เป็นคำตอบที่ 'ผิด' มากที่สุดใน SO หรือเปล่า คำตอบไม่ได้พูดถึงเว็บ api ซึ่งแตกต่างจากเว็บแอปพลิเคชัน mvc มาก! กดไลค์ @B413 ฉันตกใจมาก!
stt106

15

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

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}

จากฝั่งไคลเอ็นต์ผู้ช่วยนี้สร้างHttpClientส่วนหัวการรับรองความถูกต้องด้วย:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}

แค่ต้องการแสดงความคิดเห็นว่าฉันกำลังมองหาวิธีง่ายๆในการใช้มาตรฐานอุตสาหกรรมเพื่อส่งผ่านข้อมูลรับรองในส่วนหัว ตัวอย่างนี้แสดงพื้นฐานจากทั้งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์และเป็นสิ่งที่ฉันต้องการ
da_jokker

9

ฉันกำลังทำงานกับโครงการ MVC5 / Web API และจำเป็นต้องได้รับอนุญาตสำหรับวิธีการของ Web Api เมื่อโหลดมุมมองดัชนีของฉันครั้งแรกฉันโทรไปยังวิธี 'โทเค็น' เว็บ API ซึ่งฉันเชื่อว่าถูกสร้างขึ้นโดยอัตโนมัติ

โค้ดฝั่งไคลเอ็นต์ (CoffeeScript) เพื่อรับโทเค็นคือ:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken

หากสำเร็จจะมีการเรียกสิ่งต่อไปนี้ซึ่งจะบันทึกโทเค็นการตรวจสอบความถูกต้องภายในเครื่อง:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token

ถ้าฉันต้องการโทร Ajax ไปยังวิธี Web API ที่มีแท็ก [อนุญาต] ฉันก็เพิ่มหัวข้อต่อไปนี้ในการโทร Ajax ของฉัน:

{ "Authorization": "Bearer " + window.authenticationToken }

ซึ่งresponse.access_tokenมาจากไหน คุณกำลังตั้งค่าจาก c # code .. หรือไม่
shashwat

วัตถุ 'การตอบสนอง' ถูกส่งคืนโดยเมธอด 'token'
ProfNimrod

ฉันไม่ได้ดูบทบาท วิธีนี้ช่วยให้คุณเข้าถึงโทเค็นเพื่อให้คุณสามารถเรียกวิธีการของ WebApi ที่ตกแต่งด้วยแท็ก [อนุญาต] ก่อนอื่นเมื่อคุณเรียกใช้วิธีการใด ๆ เหล่านั้นคุณสามารถตรวจสอบบทบาทได้ stackoverflow.com/questions/19689570/mvc-5-check-user-roleอาจช่วยได้
ProfNimrod

และในโซลูชันนี้คุณรับรองความถูกต้องของผู้ใช้จริงหรือไม่
Craig Brett

ปลายทาง / โทเค็นถูกสร้างขึ้นโดยอัตโนมัติสำหรับโครงการ Web API ใหม่ใด ๆ รหัสที่อยู่เบื้องหลังนี่คือที่ที่ผู้ใช้รับรองความถูกต้อง มันซับซ้อนกว่านี้เล็กน้อยถ้าคุณเพิ่มตัวควบคุม Web API ในโครงการ MVC ที่มีอยู่
ProfNimrod
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.