ฉันจะระงับกล่องโต้ตอบการตรวจสอบสิทธิ์ของเบราว์เซอร์ได้อย่างไร


85

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

  1. เว็บเซิร์ฟเวอร์พิจารณาว่าแม้ว่าคำขอจะมีส่วนหัวการอนุญาตที่มีรูปแบบที่ดี แต่ข้อมูลประจำตัวในส่วนหัวจะไม่สามารถพิสูจน์ตัวตนได้สำเร็จ
  2. เว็บเซิร์ฟเวอร์ส่งคืนรหัสสถานะ 401 และมีส่วนหัว WWW-Authenticate อย่างน้อยหนึ่งรายการแสดงประเภทการรับรองความถูกต้องที่สนับสนุน
  3. เบราว์เซอร์ตรวจพบว่าการตอบสนองต่อการเรียกของฉันบนอ็อบเจ็กต์ XMLHttpRequest คือ 401 และการตอบสนองรวมถึงส่วนหัว WWW-Authenticate จากนั้นจะปรากฏกล่องโต้ตอบการตรวจสอบความถูกต้องเพื่อถามชื่อผู้ใช้และรหัสผ่านอีกครั้ง

ทั้งหมดนี้ใช้ได้ดีจนถึงขั้นตอนที่ 3 ฉันไม่ต้องการให้กล่องโต้ตอบปรากฏขึ้นฉันต้องการจัดการการตอบสนอง 401 ในฟังก์ชันการโทรกลับ AJAX ของฉัน (ตัวอย่างเช่นการแสดงข้อความแสดงข้อผิดพลาดในหน้าล็อกอิน) แน่นอนว่าฉันต้องการให้ผู้ใช้ป้อนชื่อผู้ใช้และรหัสผ่านอีกครั้ง แต่ฉันต้องการให้พวกเขาเห็นแบบฟอร์มการเข้าสู่ระบบที่เป็นมิตรและมั่นใจของฉันไม่ใช่ค่าเริ่มต้นของเบราว์เซอร์ที่น่าเกลียด กล่องโต้ตอบการตรวจสอบสิทธิ์

บังเอิญฉันไม่สามารถควบคุมเซิร์ฟเวอร์ได้ดังนั้นการส่งคืนรหัสสถานะที่กำหนดเอง (เช่นอย่างอื่นที่ไม่ใช่ 401) จึงไม่ใช่ตัวเลือก

มีวิธีใดบ้างที่ฉันสามารถระงับกล่องโต้ตอบการตรวจสอบสิทธิ์ได้ โดยเฉพาะอย่างยิ่งฉันสามารถระงับกล่องโต้ตอบที่จำเป็นในการตรวจสอบสิทธิ์ใน Firefox 2 หรือใหม่กว่าได้หรือไม่ มีวิธีใดในการระงับกล่องโต้ตอบConnect to [host]ใน IE 6 และใหม่กว่า


แก้ไข
ข้อมูลเพิ่มเติมจากผู้เขียน (18 ก.ย. ):
ฉันควรเพิ่มว่าปัญหาที่แท้จริงของกล่องโต้ตอบการตรวจสอบสิทธิ์ของเบราว์เซอร์ที่ปรากฏขึ้นคือการให้ข้อมูลที่ไม่เพียงพอแก่ผู้ใช้

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

โต้ตอบทำให้การรับรู้ของความจริงที่ไม่มีเขาก็ไม่ใส่ชื่อผู้ใช้และรหัสผ่าน ไม่ได้ระบุอย่างชัดเจนว่ามีปัญหาและเขาควรลองอีกครั้ง แต่กล่องโต้ตอบจะแสดงข้อมูลที่เป็นความลับแก่ผู้ใช้เช่น "ไซต์ระบุว่า:" [realm] "" โดยที่[realm]เป็นชื่ออาณาจักรสั้น ๆ ที่มีเพียงโปรแกรมเมอร์เท่านั้นที่ชื่นชอบ

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


1
คำตอบคือไม่มีคำตอบที่ดี การแฮ็กที่ Marijn แนะนำนั้นใกล้เคียงที่สุด แน่นอนว่าการใช้การรับรองความถูกต้องแบบกำหนดเองที่เซิร์ฟเวอร์และ JavaScript ของคุณเข้าใจ แต่ไม่ใช่โดยเบราว์เซอร์ก็จะใช้กลอุบายเช่นกันหากเป็นไปได้
dgvid

ฉันเคยประสบปัญหาเดียวกันและพบลิงก์นี้ในความคิดเห็นที่นี่ใน stackoverflow (ไม่ใช่บล็อกของฉัน): loudvchar.blogspot.ca/2010/11/…หวังว่ามันจะช่วยคุณได้
gies0r

คำตอบ:


17

ฉันไม่คิดว่าจะเป็นไปได้ - ถ้าคุณใช้การใช้งานไคลเอนต์ HTTP ของเบราว์เซอร์มันจะปรากฏขึ้นในกล่องโต้ตอบนั้นเสมอ สองแฮ็กอยู่ในใจ:

  1. บางที Flash อาจจัดการสิ่งนี้แตกต่างออกไป (ฉันยังไม่ได้ลอง) ดังนั้นการมีภาพยนตร์แฟลชทำให้คำขออาจช่วยได้

  2. คุณสามารถตั้งค่า 'พร็อกซี' สำหรับบริการที่คุณกำลังเข้าถึงบนเซิร์ฟเวอร์ของคุณเองและให้มันแก้ไขส่วนหัวการตรวจสอบความถูกต้องเล็กน้อยเพื่อไม่ให้เบราว์เซอร์จำได้


"เป็นไปไม่ได้" ดูเหมือนจะเป็นคำตอบที่ถูกต้องแม้ว่าฉันจะสงสัยว่าแฮ็ค "พร็อกซี" จะทำกลอุบาย
dgvid

@Stobor คำตอบที่ได้รับการยอมรับสำหรับรายการซ้ำที่คุณโพสต์ลิงก์กลับมาที่คำถามนี้เป็นคำตอบ!
8bitjunkie

3
@ 7SpecialGems จับดี. ฉันไม่ได้แนะนำว่ามันเป็นคนหลอกลวงฉันเชื่อมโยงกับคำตอบที่เฉพาะเจาะจง (WWW-Authenticate one) ซึ่งโพสต์ 4 ปีหลังจากคำตอบที่ยอมรับ แม้ว่าจะมองย้อนกลับไป แต่ฉันก็จำไม่ได้ว่าทำไมฉันถึงมองไปที่สิ่งนั้นหรือฉันทดสอบมันอย่างไร
Stobor

1
ฉันพยายามจับข้อผิดพลาด 401 ที่ไม่ได้รับอนุญาตจากรหัสนี้: $ .ajaxSetup ({statusCode: {401: function () {RedirectToLogin ();}}}); แต่ IE จะแสดงกล่องโต้ตอบการตรวจสอบสิทธิ์ของเบราว์เซอร์เสมอ ฉันจะระงับไดอะล็อกนี้ใน ASP.Net MVC 2 ได้อย่างไร
PaulP

@PaulP อย่างที่ได้กล่าวไปแล้วคุณต้องมีพร็อกซีที่จะตัดการตอบสนองรหัสสถานะ 401 ของส่วนหัว WWW-Authenticate หรือการใช้งานเซิร์ฟเวอร์ที่กำหนดเองบางประเภท
Motes

51

ฉันพบปัญหาเดียวกันที่นี่และวิศวกรแบ็กเอนด์ที่ บริษัท ของฉันได้ใช้พฤติกรรมที่เห็นได้ชัดว่าเป็นแนวทางปฏิบัติที่ดี: เมื่อการเรียก URL ส่งคืน 401 หากไคลเอนต์ตั้งค่าส่วนหัวX-Requested-With: XMLHttpRequestเซิร์ฟเวอร์จะลบwww-authenticateส่วนหัวใน การตอบสนอง

ผลข้างเคียงคือป๊อปอัปการรับรองความถูกต้องเริ่มต้นไม่ปรากฏขึ้น

ตรวจสอบให้แน่ใจว่าการเรียก API ของคุณมีชุดส่วนหัวX-Requested-With XMLHttpRequestหากเป็นเช่นนั้นไม่มีอะไรให้ทำนอกจากเปลี่ยนพฤติกรรมเซิร์ฟเวอร์ตามแนวปฏิบัติที่ดีนี้ ...


3
หากแบ็กเอนด์เป็นแบบ Java / Spring ระบบDelegatingAuthenticationEntryPointจะจัดการพฤติกรรมนี้ให้คุณ
Derek Slife

ขอบคุณสำหรับสิ่งนี้. ห้องสมุดหลายแห่งนำพฤติกรรมนี้ไปใช้รวมถึง
Devise

1
มีความคิดอย่างไรในการทำ nginx "เมื่อการเรียกไปยัง URL ส่งกลับ 401 หากไคลเอนต์ตั้งค่าส่วนหัว X-Requested-With: XMLHttpRequest เซิร์ฟเวอร์จะลดส่วนหัวของ www-authenticate ในการตอบกลับ"
markmnl

18

เบราว์เซอร์จะแสดงข้อความแจ้งการเข้าสู่ระบบเมื่อตรงตามเงื่อนไขทั้งสองต่อไปนี้:

  1. สถานะ HTTP คือ 4xx
  2. WWW-Authenticate มีส่วนหัวอยู่ในการตอบกลับ

หากคุณสามารถควบคุมการตอบกลับ HTTP คุณสามารถลบWWW-Authenticateส่วนหัวออกจากการตอบสนองและเบราว์เซอร์จะไม่แสดงกล่องโต้ตอบการเข้าสู่ระบบ

หากคุณไม่สามารถควบคุมการตอบกลับได้คุณสามารถตั้งค่าพร็อกซีเพื่อกรองWWW-Authenticateส่วนหัวออกจากการตอบกลับ

เท่าที่ฉันรู้ (อย่าลังเลที่จะแก้ไขฉันถ้าฉันผิด) ไม่มีวิธีใดที่จะป้องกันพรอมต์การเข้าสู่ระบบเมื่อเบราว์เซอร์ได้รับWWW-Authenticateส่วนหัว


ข้อมูลที่ดี. เกี่ยวกับWWW-Authenticateค่าส่วนหัวที่ถูกต้องโปรดดูstackoverflow.com/a/1748451/225217
Brice Roncace

6

ฉันตระหนักดีว่าคำถามนี้และคำตอบนั้นเก่ามาก แต่ฉันลงเอยที่นี่ บางทีคนอื่นก็จะเช่นกัน

หากคุณสามารถเข้าถึงรหัสสำหรับบริการเว็บที่ส่งคืน 401 เพียงแค่เปลี่ยนบริการเพื่อส่งคืน 403 (ต้องห้าม) ในสถานการณ์นี้แทน 401 เบราว์เซอร์จะไม่พร้อมท์สำหรับข้อมูลรับรองในการตอบสนอง 403 403 คือ รหัสที่ถูกต้องสำหรับผู้ใช้ที่ได้รับการพิสูจน์ตัวตนที่ไม่ได้รับอนุญาตสำหรับทรัพยากรเฉพาะ ซึ่งน่าจะเป็นสถานการณ์ของอปท.

จากเอกสาร IETF บน 403:

เซิร์ฟเวอร์ที่ได้รับข้อมูลรับรองที่ถูกต้องซึ่งไม่เพียงพอในการเข้าถึงควรตอบสนองด้วยรหัสสถานะ 403 (Forbidden)


4

ใน Mozilla คุณสามารถทำได้ด้วยสคริปต์ต่อไปนี้เมื่อคุณสร้างวัตถุ XMLHttpRequest:

xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);

บรรทัดที่ 2 ป้องกันกล่องโต้ตอบ ....


1
ดูเหมือนว่าจะไม่ทำอะไรเลยภายใต้ Firefox 2 ส่งผลให้เกิดข้อผิดพลาดด้านความปลอดภัย DOM รหัส NS_ERROR_DOM_SECURITY_ERR 1000 ภายใต้ Firefox 3
dgvid

2

คุณใช้เทคโนโลยีเซิร์ฟเวอร์ใดและมีผลิตภัณฑ์เฉพาะที่คุณใช้ในการตรวจสอบสิทธิ์หรือไม่

เนื่องจากเบราว์เซอร์ทำงานได้เพียงอย่างเดียวฉันเชื่อว่าคุณต้องเปลี่ยนแปลงสิ่งต่างๆในฝั่งเซิร์ฟเวอร์เพื่อไม่ให้ส่งคืนรหัสสถานะ 401 ซึ่งสามารถทำได้โดยใช้แบบฟอร์มการรับรองความถูกต้องแบบกำหนดเองที่เพียงแค่คืนฟอร์มอีกครั้งเมื่อการพิสูจน์ตัวตนล้มเหลว


2

ใน Mozilla land การตั้งค่าพารามิเตอร์ mozBackgroundRequest ของ XMLHttpRequest ( docs ) เป็น true จะยับยั้งไดอะล็อกเหล่านั้นและทำให้การร้องขอล้มเหลว อย่างไรก็ตามฉันไม่ทราบว่าการรองรับข้ามเบราว์เซอร์นั้นดีเพียงใด (รวมถึงคุณภาพของข้อมูลข้อผิดพลาดในคำขอที่ล้มเหลวนั้นดีมากในทุกเบราว์เซอร์หรือไม่)


moz- นำหน้าแสดงว่าไม่มีการสนับสนุนข้ามเบราว์เซอร์ (เว้นแต่คุณจะพบพารามิเตอร์ที่คล้ายกันซึ่งทำงานในเบราว์เซอร์อื่น ๆ แต่ละตัว)
Brilliand

2

jan.vdbergh มีความจริงถ้าคุณสามารถเปลี่ยน 401 ในฝั่งเซิร์ฟเวอร์สำหรับรหัสสถานะอื่นเบราว์เซอร์จะไม่จับและทาสีป๊อปอัป อีกวิธีหนึ่งอาจเปลี่ยนส่วนหัว WWW-Authenticate สำหรับส่วนหัวที่กำหนดเองอื่น ฉันไม่เชื่อว่าทำไมเบราว์เซอร์ที่แตกต่างกันไม่สามารถรองรับได้ใน Firefox ไม่กี่เวอร์ชันเราสามารถทำคำขอ xhr ด้วย mozBackgroundRequest แต่ในเบราว์เซอร์อื่น ๆ ?? ที่นี่มีลิงก์ที่น่าสนใจเกี่ยวกับปัญหานี้ใน Chromium


1

ฉันมีปัญหาเดียวกันกับ MVC 5 และ VPN เมื่อใดก็ตามที่เราอยู่นอก DMZ โดยใช้ VPN เราพบว่าตัวเองต้องตอบข้อความของเบราว์เซอร์นี้ การใช้. net ฉันเพียงแค่จัดการการกำหนดเส้นทางของข้อผิดพลาดโดยใช้

<customErrors defaultRedirect="~/Error"  >
  <error statusCode="401" redirect="~/Index"/>
</customErrors>

จนถึงตอนนี้มันใช้งานได้เนื่องจากการดำเนินการดัชนีภายใต้ตัวควบคุมภายในบ้านตรวจสอบผู้ใช้ มุมมองในการดำเนินการนี้หากการเข้าสู่ระบบไม่สำเร็จจะมีการควบคุมการเข้าสู่ระบบที่ฉันใช้เพื่อล็อกผู้ใช้โดยใช้แบบสอบถาม LDAP ที่ส่งผ่านไปยัง Directory Services:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
      DirectorySearcher Dsearch = new DirectorySearcher(entry);
      Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
      Dsearch.PropertiesToLoad.Add("cn");

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


1

ฉันใช้ Node, Express & Passport และกำลังประสบปัญหาเดียวกัน ฉันทำให้มันใช้งานได้โดยตั้งค่าwww-authenticateส่วนหัวเป็นสตริงว่างอย่างชัดเจน ในกรณีของฉันดูเหมือนว่า:

(err, req, res, next) => {
  if (err) {
    res._headers['www-authenticate'] = ''
    return res.json(err)
  }
}

ฉันหวังว่าจะช่วยใครสักคน!


0

สำหรับผู้ที่ยกเลิกการใช้ C # นี่คือActionAttributeสิ่งที่ส่งกลับ400แทน401และกล่องโต้ตอบการตรวจสอบสิทธิ์ขั้นพื้นฐาน "กลืน"

public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new HttpStatusCodeResult(400);
    }
}

ใช้ดังต่อไปนี้:

[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
 // your code goes here
}

หวังว่านี่จะช่วยคุณประหยัดเวลาได้บ้าง

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