Làm cách nào để ngăn trình duyệt gọi cửa sổ bật lên xác thực cơ bản và xử lý lỗi 401 bằng cách sử dụng Jquery?


107

Tôi cần gửi yêu cầu ủy quyền bằng xác thực cơ bản. Tôi đã thực hiện thành công điều này bằng cách sử dụng jquery. Tuy nhiên, khi tôi gặp lỗi 401, cửa sổ bật lên trình duyệt auth cơ bản được mở và không gọi lại lỗi jquery ajax.


Câu trả lời:


46

Tôi cũng phải đối mặt với vấn đề này gần đây. Vì bạn không thể thay đổi hành vi mặc định của trình duyệt hiển thị popup trong trường hợp của một 401( cơ bản hoặc tiêu hóa xác thực), có hai cách để sửa lỗi này:

  • Thay đổi phản hồi của máy chủ để không trả về a 401. 200Thay vào đó, hãy trả lại mã và xử lý mã này trong ứng dụng khách jQuery của bạn.
  • Thay đổi phương thức bạn đang sử dụng để ủy quyền thành một giá trị tùy chỉnh trong tiêu đề của bạn. Các trình duyệt sẽ hiển thị cửa sổ bật lên cho BasicDigest . Bạn phải thay đổi điều này trên cả máy khách và máy chủ.

    headers : {
      "Authorization" : "BasicCustom"
    }

Hãy cũng xem phần này để biết ví dụ về việc sử dụng jQuery với Basic Auth.


10
WWW-Authenticate: xBasic domains = com.example có thể làm điều đó, cùng với mã trạng thái cổ điển 401. bài đăng trên blog này đã cho tôi thấy gợi ý (tôi không phải là chủ sở hữu của blog) tovchar.blogspot.ca/2010/11/…
PM

2
@PM, câu trả lời của blog là một giải pháp hoàn hảo. Lưu ý rằng nếu sử dụng <security:http-basic/>bạn không cần định nghĩa basicAuthenticationFiltermà nên định nghĩa nó là <security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>.
Brett Ryan,

Bạn có thể cho tôi biết cách ghi đè phản hồi trước khi gửi lại cho khách hàng không, tôi đang sử dụng jaxrs với xác thực cơ bản. tôi cần ghi đè lớp nào để sửa đổi phản hồi?
mohammed sameen

Vì lý do nào đó, tôi nhận được cửa sổ bật lên khi trả về a 401WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:NegotiateBạn có biết tại sao điều đó lại như vậy không
DevEng 16/02/18

34

Trả lại mã trạng thái chung 400, sau đó xử lý phía máy khách.

Hoặc bạn có thể giữ 401 và không trả lại tiêu đề WWW-Authenticate, đây thực sự là những gì trình duyệt đang phản hồi với cửa sổ bật lên xác thực. Nếu thiếu tiêu đề WWW-Authenticate, thì trình duyệt sẽ không nhắc nhập thông tin đăng nhập.


6
@MortenHaraldsen Vâng, phản hồi 401 là phản hồi thích hợp để đưa ra trong trường hợp này, vấn đề là trình duyệt đang tự động xử lý điều này theo cách nguyên bản, thay vì cho phép ứng dụng javascript xử lý nó. Bạn có thể tuân theo tiêu chuẩn, bằng cách không trả lại phản hồi thích hợp mà tiêu chuẩn đề xuất hoặc bạn có thể chọn không tuân theo tiêu chuẩn, bằng cách trả lại mã phản hồi được đề xuất tiêu chuẩn. Hãy lựa chọn của bạn :)
Ibraheem

Trong ứng dụng express của mình, tôi đã sửa lỗi này bằng một dòng: res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
gstroup 13/02/16

1
@Ibraheem, không thể tự mình nói rõ hơn. Các tiêu chuẩn được tạo ra bởi những người ngồi xuống và nói chuyện, không nhất thiết phải là những người ngồi xuống và viết mã.
user2867288

15

Bạn có thể chặn cửa sổ bật lên xác thực cơ bản với url yêu cầu giống như sau:

https://username:password@example.com/admin/...

Nếu bạn gặp lỗi 401 (tên người dùng hoặc mật khẩu sai), nó sẽ được xử lý chính xác bằng lệnh gọi lại lỗi jquery. Nó có thể gây ra một số vấn đề bảo mật (trong trường hợp giao thức http thay vì https), nhưng nó hoạt động.

UPD: Hỗ trợ giải pháp này sẽ bị xóa trong Chrome 59


KINH NGẠC!!!! Đã giải quyết sự cố của tôi vì sự cố đang thử 192.168.1.1 và bộ định tuyến liên tục yêu cầu Auth.
Nadav Lebovitch

Nếu bạn đi tới tab "Mạng" trong Công cụ dành cho nhà phát triển, trong bất kỳ trình duyệt nào, bạn có thể đọc tên người dùng và mật khẩu ở dạng văn bản thuần túy. Nó hoạt động, mặc dù.
Bruno Finger

19
Xin đừng bao giờ làm điều này, các bản ghi yêu cầu trên máy chủ web của bạn bây giờ có giá trị hơn nhiều đối với tôi .. Tên người dùng và mật khẩu kết hợp miễn phí cộng với mã phản hồi! Cảm ơn
Remco

nhưng làm thế nào có thể ai đó ngăn chặn tên người dùng và mật khẩu từ đang được xem
sdx11

3
Phương thức xác thực này đang trở nên mất giá trị và Chrome sẽ ngừng hỗ trợ thông tin đăng nhập được nhúng, tức là https://user:pass@host/trong M59 vào khoảng tháng 6 năm 2017. Hãy xem bài đăng trên blog chromestatus này để biết thêm thông tin.
Garywoo

13

Như những người khác đã chỉ ra, cách duy nhất để thay đổi hành vi của trình duyệt là đảm bảo phản hồi không chứa mã trạng thái 401 hoặc nếu có thì không bao gồm WWW-Authenticate: Basictiêu đề. Vì việc thay đổi mã trạng thái không phù hợp với ngữ nghĩa và không mong muốn, một cách tiếp cận tốt là loại bỏ WWW-Authenticatetiêu đề. Nếu bạn không thể hoặc không muốn sửa đổi ứng dụng máy chủ web của mình, bạn luôn có thể cung cấp hoặc ủy quyền nó thông qua Apache (nếu bạn chưa sử dụng Apache).

Đây là cấu hình để Apache viết lại phản hồi để loại bỏ tiêu đề WWW-Authenticate IFF mà yêu cầu chứa tiêu đề X-Requested-With: XMLHttpRequest(được đặt theo mặc định bởi các khung Javascript chính như JQuery / AngularJS, v.v.) VÀ phản hồi chứa đầu trang WWW-Authenticate: Basic.

Đã thử nghiệm trên Apache 2.4 (không chắc liệu nó có hoạt động với 2.2 hay không). Điều này phụ thuộc vào mod_headersmô-đun được cài đặt. (Trên Debian / Ubuntu sudo a2enmod headersvà khởi động lại Apache)

    <Location />
            # Make sure that if it is an XHR request,
            # we don't send back basic authentication header.
            # This is to prevent the browser from displaying a basic auth login dialog.
            Header unset WWW-Authenticate "expr=req('X-Requested-With') == 'XMLHttpRequest' && resp('WWW-Authenticate') =~ /^Basic/"
    </Location>   

1
Để thực hiện điều tương tự với Nginx, setproxy_hide_header WWW-Authenticate;
Cuga

7

Sử dụng X-Request-With: XMLHttpRequest với tiêu đề yêu cầu của bạn. Vì vậy, tiêu đề phản hồi sẽ không chứa WWW-Authenticate: Basic.

beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', ("Basic "
                        .concat(btoa(key))));
                    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                },

1
Điều đó không ảnh hưởng gì đến tôi. Bạn đang sử dụng loại máy chủ nào mà WWW-Authenticate không được gửi đi kèm khi bạn đặt XMLHttpRequest?
Robert Antonucci

@RobertAntonucci nó apache tomcat
sedhu

5

Nếu bạn đang sử dụng Máy chủ IIS, bạn có thể thiết lập Ghi lại URL IIS (v2) để ghi lại WWW-Authenticationtiêu đề thànhNone trên URL được yêu cầu.

Hướng dẫn tại đây .

Giá trị bạn muốn thay đổi là response_www_authenticate .

Nếu bạn cần thêm thông tin, hãy thêm nhận xét và tôi sẽ đăng tệp web.config.


1
Điều này làm việc rất tốt. Tôi muốn lưu ý rằng phần "phản hồi" phải được viết là "RESPONSE_www_authenticate" trong URL Rewrite v2 trên IIS 7.5.
Michael Freeman

3

Nếu tiêu đề WWW-Authenticate bị xóa, thì bạn sẽ không nhận được bộ nhớ đệm của thông tin đăng nhập và sẽ không lấy lại tiêu đề Ủy quyền theo yêu cầu. Điều đó có nghĩa là bây giờ bạn sẽ phải nhập thông tin đăng nhập cho mọi yêu cầu mới mà bạn tạo.


Điều này là rất quan trọng, hoàn toàn đúng chỗ.
Tez Wingfield

2

Ngoài ra, nếu bạn có thể tùy chỉnh phản hồi máy chủ của mình, bạn có thể trả về 403 Forbidden.

Trình duyệt sẽ không mở cửa sổ bật lên xác thực và lệnh gọi lại jquery sẽ được gọi.


5
Điều đó đi ngược lại đặc điểm kỹ thuật HTTP 1.1, nơi được tuyên bố rằng "... Việc ủy ​​quyền sẽ không giúp ích được gì và yêu cầu KHÔNG ĐƯỢC lặp lại".
Jukka Dahlbom

1
Việc nhận 403 là hợp lệ khi được xác thực cho các tài nguyên mà bạn không được phép truy cập, 401 nên được gửi ở nơi bạn chưa được xác thực.
Brett Ryan,

1

Trong Safari, bạn có thể sử dụng các yêu cầu đồng bộ để tránh trình duyệt hiển thị cửa sổ bật lên. Tất nhiên, yêu cầu đồng bộ chỉ nên được sử dụng trong trường hợp này để kiểm tra thông tin đăng nhập của người dùng ... Bạn có thể sử dụng yêu cầu như vậy trước khi gửi yêu cầu thực sự, điều này có thể gây ra trải nghiệm người dùng không tốt nếu nội dung (được gửi hoặc nhận) khá nặng.

    var xmlhttp=new XMLHttpRequest;
    xmlhttp.withCredentials=true;
    xmlhttp.open("POST",<YOUR UR>,false,username,password);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

Trong các ngữ cảnh khác, sử dụng "OPTIONS" thay vì "POST" cũng có thể hữu ích.
Emmanuel Sellier

0

Tạo một / url đăng nhập, thay vì chấp nhận các tham số "người dùng" và "mật khẩu" thông qua GET và không yêu cầu xác thực cơ bản. Tại đây, sử dụng php, node, java, bất cứ thứ gì và phân tích cú pháp tệp mật khẩu của bạn và khớp các tham số (người dùng / thẻ) với nó. Nếu có khớp, hãy chuyển hướng đến http: // user: pass@domain.com/ (điều này sẽ đặt thông tin đăng nhập trên trình duyệt của bạn) nếu không, hãy gửi phản hồi 401 (không có tiêu đề WWW-Authenticate).


Điều đó sẽ cực kỳ tuyệt vời cho bất kỳ ai đang cố gắng đánh hơi tên người dùng / mật khẩu từ người đàn ông văn bản thuần túy trong các cuộc tấn công giữa!
Ajax

0

Từ mặt sau với Spring Boot, tôi đã sử dụng BasicAuthenticationEntryPoint tùy chỉnh:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().authorizeRequests()
            ...
            .antMatchers(PUBLIC_AUTH).permitAll()
            .and().httpBasic()
//    https://www.baeldung.com/spring-security-basic-authentication
            .authenticationEntryPoint(authBasicAuthenticationEntryPoint())
            ...

@Bean
public BasicAuthenticationEntryPoint authBasicAuthenticationEntryPoint() {
    return new BasicAuthenticationEntryPoint() {
        {
            setRealmName("pirsApp");
        }

        @Override
        public void commence
                (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
                throws IOException, ServletException {
            if (request.getRequestURI().equals(PUBLIC_AUTH)) {
                response.sendError(HttpStatus.PRECONDITION_FAILED.value(), "Wrong credentials");
            } else {
                super.commence(request, response, authEx);
            }
        }
    };
}
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.