Làm cách nào để chặn hộp thoại xác thực của trình duyệt?


85

Ứng dụng web của tôi có một trang đăng nhập gửi thông tin xác thực thông qua cuộc gọi AJAX. Nếu người dùng nhập đúng tên người dùng và mật khẩu, mọi thứ đều ổn, nhưng nếu không, điều sau sẽ xảy ra:

  1. Máy chủ web xác định rằng mặc dù yêu cầu bao gồm tiêu đề Ủy quyền được định dạng tốt, nhưng thông tin đăng nhập trong tiêu đề không xác thực thành công.
  2. Máy chủ web trả về mã trạng thái 401 và bao gồm một hoặc nhiều tiêu đề WWW-Authenticate liệt kê các loại xác thực được hỗ trợ.
  3. Trình duyệt phát hiện rằng phản hồi cho cuộc gọi của tôi trên đối tượng XMLHttpRequest là 401 và phản hồi bao gồm các tiêu đề WWW-Authenticate. Sau đó, nó bật lên một hộp thoại xác thực hỏi lại tên người dùng và mật khẩu.

Mọi việc đều ổn cho đến bước 3. Tôi không muốn hộp thoại bật lên, tôi muốn xử lý phản hồi 401 trong hàm gọi lại AJAX của mình. (Ví dụ: bằng cách hiển thị thông báo lỗi trên trang đăng nhập.) Tất nhiên, tôi muốn người dùng nhập lại tên người dùng và mật khẩu của họ, nhưng tôi muốn họ thấy biểu mẫu đăng nhập thân thiện, yên tâm của tôi chứ không phải biểu mẫu mặc định xấu xí của trình duyệt hộp thoại xác thực.

Ngẫu nhiên, tôi không có quyền kiểm soát máy chủ, vì vậy để nó trả về mã trạng thái tùy chỉnh (tức là một cái gì đó khác với 401) không phải là một tùy chọn.

Có cách nào để tôi có thể chặn hộp thoại xác thực không? Đặc biệt, tôi có thể chặn hộp thoại Yêu cầu Xác thực trong Firefox 2 trở lên không? Có cách nào để chặn hộp thoại Kết nối với [máy chủ] trong IE 6 trở lên không?


Chỉnh sửa
Thông tin bổ sung từ tác giả (ngày 18 tháng 9):
Tôi nên nói thêm rằng vấn đề thực sự với hộp thoại xác thực của trình duyệt bật lên là nó cung cấp không đủ thông tin cho người dùng.

Người dùng vừa nhập tên người dùng và mật khẩu qua biểu mẫu trên trang đăng nhập, anh ta tin rằng mình đã nhập chính xác cả hai và anh ta đã nhấp vào nút gửi hoặc nhấn enter. Kỳ vọng của anh ta là anh ta sẽ được đưa đến trang tiếp theo hoặc có thể được thông báo rằng anh ta đã nhập sai thông tin của mình và nên thử lại. Tuy nhiên, thay vào đó, anh ta xuất hiện với một hộp thoại bất ngờ.

Hộp thoại làm cho không có sự thừa nhận của thực tế, ông chỉ làm nhập tên người dùng và mật khẩu. Nó không nói rõ rằng đã xảy ra sự cố và anh ta nên thử lại. Thay vào đó, hộp thoại hiển thị cho người dùng thông tin khó hiểu như "Trang web nói: ' [cảnh giới] '." Nơi [cảnh giới] là một tên gọi ngắn gọn của lĩnh vực mà chỉ một lập trình viên mới có thể yêu thích.

Các nhà thiết kế web broswer lưu ý: không ai hỏi làm thế nào để chặn hộp thoại xác thực nếu bản thân hộp thoại đó thân thiện hơn với người dùng. Các toàn bộ lý do mà tôi đang làm một hình thức đăng nhập là đội ngũ quản lý sản phẩm của chúng tôi một cách đúng đắn xem xét các hộp thoại xác thực của các trình duyệt là khủng khiếp.


1
Câu trả lời là không có câu trả lời nào tốt. Các thủ thuật do Marijn gợi ý gần như đạt được. Tất nhiên, sử dụng xác thực tùy chỉnh được hiểu bởi máy chủ và JavaScript của bạn, nhưng không phải bởi trình duyệt, cũng sẽ thực hiện thủ thuật, nếu điều đó có thể.
dgvid 30/09/09

Tôi đã gặp vấn đề tương tự và tìm thấy liên kết này trong một bình luận ở đây trên stackoverflow (không phải blog của tôi) : oudvchar.blogspot.ca/2010/11/… Hy vọng nó sẽ giúp ích cho bạn.
gies0r

Câu trả lời:


17

Tôi không nghĩ rằng điều này là có thể - nếu bạn sử dụng triển khai máy khách HTTP của trình duyệt, nó sẽ luôn bật lên hộp thoại đó. Hai thủ thuật xuất hiện trong tâm trí:

  1. Có thể Flash xử lý điều này theo cách khác (tôi chưa thử), vì vậy có một bộ phim flash thực hiện yêu cầu có thể giúp ích.

  2. Bạn có thể thiết lập 'proxy' cho dịch vụ mà bạn đang truy cập trên máy chủ của chính mình và để nó sửa đổi các tiêu đề xác thực một chút để trình duyệt không nhận ra chúng.


"Không thể" dường như là câu trả lời chính xác, mặc dù tôi nghi ngờ rằng hack "proxie" sẽ thực hiện thủ thuật.
dgvid 30/09/09

@Stobor Câu trả lời được chấp nhận cho bản sao mà bạn đã đăng thực sự liên kết trở lại câu hỏi này như câu trả lời của nó!
8bitjunkie

3
@ 7SpecialGems Bắt tốt. Tôi không cho rằng đó là một bản dupe, tôi đã liên kết với câu trả lời cụ thể (WWW-Authenticate) được đăng 4 năm sau khi câu trả lời được chấp nhận. Mặc dù trong nhận thức muộn màng, tôi không thể nhớ tại sao tôi lại nhìn vào nó, hoặc tôi đã kiểm tra nó như thế nào.
Stobor

1
Tôi cố gắng bắt lỗi 401 trái phép bằng mã này: $ .ajaxSetup ({statusCode: {401: function () {RedirectToLogin ();}}}); Nhưng IE luôn hiển thị hộp thoại xác thực của trình duyệt. Làm cách nào để chặn hộp thoại này trong ASP.Net MVC 2?
PaulP

@PaulP, giống như đã nói, bạn cần một proxy sẽ loại bỏ phản hồi mã trạng thái 401 của tiêu đề WWW-Authenticate của họ hoặc một số loại triển khai máy chủ tùy chỉnh.
27/12/15

51

Tôi gặp phải vấn đề tương tự ở đây và kỹ sư phụ trợ tại công ty của tôi đã triển khai một hành vi dường như được coi là một thực tiễn tốt: khi một lệnh gọi đến URL trả về 401, nếu khách hàng đã đặt tiêu đề X-Requested-With: XMLHttpRequest, máy chủ sẽ bỏ www-authenticatetiêu đề đó phản ứng.

Tác dụng phụ là cửa sổ bật lên xác thực mặc định không xuất hiện.

Đảm bảo rằng lệnh gọi API của bạn có X-Requested-Withtiêu đề được đặt thành XMLHttpRequest. Nếu vậy, không có gì phải làm ngoại trừ thay đổi hành vi của máy chủ theo thông lệ tốt này ...


3
Nếu phần phụ trợ dựa trên Java / Spring, thì phần mềm DelegatingAuthenticationEntryPointsẽ xử lý hành vi này cho bạn.
Derek Slife

Cảm ơn vì điều này. Nhiều thư viện đã áp dụng hành vi này bao gồm lập mưu
josephnvu

1
bất kỳ ý tưởng làm thế nào để làm điều này trong nginx? "khi một lệnh gọi đến một URL trả về 401, nếu máy khách đã đặt tiêu đề X-Request-With: XMLHttpRequest, máy chủ sẽ loại bỏ tiêu đề www-authenticate trong phản hồi của nó."
markmnl

18

Trình duyệt bật lên lời nhắc đăng nhập khi cả hai điều kiện sau được đáp ứng:

  1. Trạng thái HTTP là 4xx
  2. WWW-Authenticate tiêu đề hiện diện trong phản hồi

Nếu bạn có thể kiểm soát phản hồi HTTP, thì bạn có thể xóa WWW-Authenticatetiêu đề khỏi phản hồi và trình duyệt sẽ không bật lên hộp thoại đăng nhập.

Nếu bạn không thể kiểm soát phản hồi, bạn có thể thiết lập proxy để lọc WWW-Authenticatetiêu đề khỏi phản hồi.

Theo như tôi biết (vui lòng sửa cho tôi nếu tôi sai), không có cách nào để ngăn lời nhắc đăng nhập khi trình duyệt nhận được WWW-Authenticatetiêu đề.


Thông tin tốt. Về hợp lệ WWW-Authenticategiá trị tiêu đề, xem stackoverflow.com/a/1748451/225217
Brice Roncace

6

Tôi nhận ra rằng câu hỏi này và các câu trả lời của nó rất cũ. Nhưng, tôi đã kết thúc ở đây. Có lẽ những người khác cũng sẽ như vậy.

Nếu bạn có quyền truy cập vào mã cho dịch vụ web trả về 401. Chỉ cần thay đổi dịch vụ để trả về 403 (Bị cấm) trong trường hợp này thay vì 401. Trình duyệt sẽ không nhắc thông tin đăng nhập để phản hồi 403. 403 là mã chính xác cho người dùng được xác thực không được ủy quyền cho một tài nguyên cụ thể. Đó dường như là tình huống của OP.

Từ tài liệu IETF trên 403:

Máy chủ nhận được thông tin xác thực hợp lệ không đủ để có được quyền truy cập phải phản hồi với mã trạng thái 403 (Bị cấm)


4

Trong Mozilla, bạn có thể đạt được nó bằng tập lệnh sau khi tạo đối tượng XMLHttpRequest:

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

Dòng thứ 2 ngăn hộp thoại ....


1
Điều này dường như không thực hiện được gì trong Firefox 2. Nó dẫn đến lỗi bảo mật DOM, mã NS_ERROR_DOM_SECURITY_ERR 1000, trong Firefox 3.
dgvid

2

Bạn sử dụng công nghệ máy chủ nào và có sản phẩm cụ thể nào bạn sử dụng để xác thực không?

Vì trình duyệt chỉ thực hiện công việc của nó, tôi tin rằng bạn phải thay đổi mọi thứ ở phía máy chủ để không trả về mã trạng thái 401. Điều này có thể được thực hiện bằng cách sử dụng các biểu mẫu xác thực tùy chỉnh mà chỉ cần trả lại biểu mẫu khi xác thực không thành công.


2

Trong đất Mozilla, việc đặt tham số mozBackgroundRequest của XMLHttpRequest ( docs ) thành true sẽ ngăn chặn các hộp thoại đó và khiến các yêu cầu đơn giản không thành công. Tuy nhiên, tôi không biết hỗ trợ trên nhiều trình duyệt tốt đến mức nào (bao gồm cả chất lượng của thông tin lỗi trên các yêu cầu không thành công đó có tốt trên các trình duyệt hay không).


Tiền tố moz- ngụ ý không hỗ trợ nhiều trình duyệt (trừ khi bạn có thể tìm thấy các tham số tương tự hoạt động trong mỗi trình duyệt khác).
Brilliand

2

jan.vdbergh có sự thật, nếu bạn có thể thay đổi 401 ở phía máy chủ cho một mã trạng thái khác, trình duyệt sẽ không bắt và vẽ cửa sổ bật lên. Một giải pháp khác có thể là thay đổi tiêu đề WWW-Authenticate cho một tiêu đề tùy chỉnh khác. Tôi không tin tại sao các trình duyệt khác nhau không thể hỗ trợ nó, trong một số phiên bản Firefox, chúng tôi có thể thực hiện yêu cầu xhr với mozBackgroundRequest, nhưng trong các trình duyệt khác ?? ở đây, có một liên kết thú vị với vấn đề này trong Chromium.


1

Tôi gặp vấn đề tương tự với MVC 5 và VPN trong đó bất cứ khi nào chúng tôi ở bên ngoài DMZ sử dụng VPN, chúng tôi thấy mình phải trả lời thông báo trình duyệt này. Sử dụng .net, tôi chỉ cần xử lý định tuyến của lỗi bằng cách sử dụng

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

cho đến nay nó đã hoạt động vì hành động Index trong bộ điều khiển gia đình xác nhận người dùng. Chế độ xem trong hành động này, nếu đăng nhập không thành công, có các điều khiển đăng nhập mà tôi sử dụng để đăng nhập người dùng bằng cách sử dụng truy vấn LDAP được chuyển vào Dịch vụ Thư mục:

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

Mặc dù điều này đã hoạt động tốt cho đến nay, và tôi phải cho bạn biết rằng tôi vẫn đang thử nghiệm nó và mã ở trên không có lý do gì để chạy vì vậy nó có thể bị xóa ... thử nghiệm hiện bao gồm cố gắng phát hiện ra trường hợp mà tập thứ hai mã không còn được sử dụng nữa. Một lần nữa, đây là một công việc đang được tiến hành, nhưng vì nó có thể giúp ích gì đó hoặc giúp bạn tìm ra một số ý tưởng, tôi quyết định bổ sung nó ngay bây giờ ... Tôi sẽ cập nhật nó với kết quả cuối cùng sau khi tất cả thử nghiệm được thực hiện.


1

Tôi đang sử dụng Node, Express & Passport và đang gặp sự cố tương tự. Tôi đã làm cho nó hoạt động bằng cách đặt www-authenticatetiêu đề một cách rõ ràng thành một chuỗi trống. Trong trường hợp của tôi, nó trông như thế này:

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

Tôi hy vọng rằng sẽ giúp một ai đó!


0

Đối với những người không gửi C #, đây là ActionAttributetrả về 400thay vì 401và 'nuốt' hộp thoại Xác thực cơ bản.

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

sử dụng như sau:

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

Hy vọng điều này giúp bạn tiết kiệm thời gian.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.