Lọc bất kỳ URI yêu cầu HTTP?


10

Tôi muốn lọc bất kỳ URI yêu cầu HTTP nào được thực hiện thông qua API HTTP.

Trường hợp sử dụng:

  1. Kiểm tra cập nhật WordPress đi đến http://api.wordpress.org/core/version-check/1.6/ , nhưng https://api.wordpress.org/core/version-check/1.6/ cũng hoạt động và tôi muốn để sử dụng cái này luôn.
  2. Tệp WordPress mới được lấy từ http://wordpress.org/wordpress-3.4.2.zip , nhưng https://wordpress.org/wordpress-3.4.2.zip cũng hoạt động.
  3. Đôi khi tôi muốn gỡ lỗi các yêu cầu và chuyển hướng các yêu cầu tạm thời sang một miền tùy chỉnh trên máy chủ cục bộ của tôi.
  4. Một số plugin tạo yêu cầu cho các máy chủ khác và tôi muốn thay thế các yêu cầu này khi máy chủ bên ngoài bị hỏng.

Các yêu cầu cập nhật là những yêu cầu quan trọng nhất hiện nay, bởi vì vẫn còn lỗi 16778 chưa được trộn ( thêm thông tin ) và HTTPS yêu cầu giảm nguy cơ tấn công Man-in-the-middle.

Tôi đã tìm kiếm kỹ lưỡng , tôi đã nghiên cứu mã cốt lõi, nhưng kết thúc giống như Nacin hai năm trước:

Tôi nghĩ chắc chắn bạn có thể lọc URL của yêu cầu HTTP, nhưng bây giờ tôi không thể tìm thấy.

Tôi đã bỏ lỡ cái gì? Tôi đã làm :)


Liên kết câu trả lời này ở đây cho bất kỳ ai tìm kiếm gỡ lỗi cURL trong WP.
kaiser

Câu trả lời:


9

Ít hơn một câu trả lời, nhưng chỉ là một danh sách những điều trực tiếp từ kinh nghiệm của tôi với nó - có thể bạn đã bỏ qua điều gì đó.

Gỡ lỗi yêu cầu và kết quả của nó

Không đào sâu 'quá sâu vào quá trình cập nhật, nhưng API HTTP HTTP sử dụng WP_HTTPlớp. Nó cũng cung cấp một điều tốt đẹp: Một cái móc gỡ lỗi.

do_action( 'http_api_debug', $response, 'response', $class, $args, $url );

Nơi $responsecũng có thể là một WP_Errorđối tượng có thể cho bạn biết nhiều hơn.

Lưu ý: Từ một thử nghiệm ngắn, bộ lọc này dường như chỉ hoạt động (vì một số lý do) hoạt động nếu bạn đặt nó gần với nơi bạn thực sự thực hiện yêu cầu. Vì vậy, có thể bạn cần gọi nó từ trong một cuộc gọi lại trên một trong các bộ lọc dưới đây.

WP_HTTP Đối số lớp

Các đối số Classes có thể lọc được, nhưng một số được đặt lại bởi các phương thức bên trong trở lại với những gì WP giả định là cần thiết.

apply_filters( 'http_request_args', $r, $url );

Một trong những đối số là ssl_verify, đúng theo mặc định (nhưng đối với tôi gây ra vấn đề lớn khi cập nhật từ - ví dụ - GitHub). Chỉnh sửa: Sau khi gỡ lỗi yêu cầu kiểm tra, tôi tìm thấy một đối số khác được đặt thành xác minh nếu SSL được đặt thành true. Nó được gọi sslverify(không phân tách dấu gạch dưới). Không biết điều này xuất hiện trong trò chơi ở đâu, nếu nó thực sự được sử dụng hoặc bị bỏ rơi và nếu bạn có cơ hội ảnh hưởng đến giá trị của nó. Tôi tìm thấy nó bằng cách sử dụng 'http_api_debug'bộ lọc.

Hoàn toàn tùy chỉnh

Bạn cũng có thể "đơn giản" ghi đè lên toàn bộ phần bên trong và đi với một thiết lập tùy chỉnh. Có một bộ lọc cho điều đó.

apply_filters( 'pre_http_request', false, $r, $url );

Các đối số đầu tiên cần phải được đặt thành đúng. Hơn bạn có thể tương tác với các đối số bên trong $rvà kết quả từ parse_url( $url );.

Ủy quyền

Một thứ khác có thể hoạt động có thể là chạy mọi thứ thông qua Proxy tùy chỉnh. Điều này cần một số cài đặt trong của bạn wp-config.php. Tôi chưa bao giờ thử điều này trước đây, nhưng tôi đã chạy qua các hằng số một lúc trước và tóm tắt một số ví dụ nên hoạt động và bao gồm một số nhận xét trong trường hợp tôi cần nó một ngày. Bạn phải xác định WP_PROXY_HOSTWP_PROXY_PORTnhư một phút. cài đặt. Khác không có gì sẽ làm việc và nó sẽ đơn giản bỏ qua proxy của bạn.

# HTTP Proxies
# Used for e.g. in Intranets
# Fixes Feeds as well
# Defines the proxy adresse.
define( 'WP_PROXY_HOST',          '127.0.84.1' );
# Defines the proxy port.
define( 'WP_PROXY_PORT',          '8080' );
# Defines the proxy username.
define( 'WP_PROXY_USERNAME',      'my_user_name' );
# Defines the proxy password.
define( 'WP_PROXY_PASSWORD',      'my_password' );
# Allows you to define some adresses which
# shouldn't be passed through a proxy.
define( 'WP_PROXY_BYPASS_HOSTS',  'localhost, www.example.com' );

BIÊN TẬP

Các WP_HTTPlớp thường đóng vai trò như cơ sở lớp (sẽ được mở rộng cho các kịch bản khác nhau). Các mở rộng WP_HTTP_*lớp học Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. Nếu bạn kết nối một cuộc gọi lại với 'http_api_debug'-action, thì đối số thứ ba sẽ cho bạn biết lớp nào đã được sử dụng cho yêu cầu của bạn.

Trong WP_HTTP_curlLớp học, bạn sẽ tìm thấy request()phương pháp. Phương pháp này cung cấp hai bộ lọc để chặn hành vi SSL: Một cho các yêu cầu cục bộ 'https_local_ssl_verify'và một cho các yêu cầu từ xa 'https_ssl_verify'. WP có thể sẽ xác định locallocalhostvà những gì bạn nhận được từ get_option( 'siteurl' );.

Vì vậy, những gì tôi cần làm là thử ngay sau đây trước khi bạn thực hiện yêu cầu đó (hoặc từ một cuộc gọi lại được nối với yêu cầu gần nhất:

add_filter( 'https_ssl_verify', '__return_true' );

# Local requests should be checked with something like
# 'localhost' === $_SERVER['HTTP_HOST'] or similar
# add_filter( 'https_local_ssl_verify', '__return_true' );

Sidenote: Trong hầu hết các trường hợp WP_HTTP_curlsẽ được sử dụng để xử lý Proxy.


1
À, tôi nghĩ bạn đã trả lời câu hỏi của tôi một cách gián tiếp: Tôi có thể móc nối pre_http_request, hủy yêu cầu và gửi lại với URL chính xác. Sẽ thử điều đó tối nay.
fuxia

8

Dựa trên câu trả lời hữu ích của @ kaiser, tôi đã viết một số mã có vẻ hoạt động tốt. Đó là lý do tại sao tôi đánh dấu nó là Câu trả lời.

Hãy để tôi giải thích giải pháp của tôi

Hợp lý

Khi một yêu cầu được gửi qua API được thực hiện WP_Http::request(). Đó là phương pháp với giáo dục

@todo Tái cấu trúc mã này.

Tiêu đề trong tiêu đề của nó. Tôi không thể đồng ý nhiều hơn.

Bây giờ, có một số bộ lọc. Tôi quyết định sử dụng sai pre_http_requestcho nhu cầu của mình:

add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );

Chúng tôi nhận được ba đối số ở đây : false, $r, $url.

  • falselà giá trị trả lại dự kiến ​​cho apply_filters(). Nếu chúng tôi gửi lại bất cứ điều gì khác, WordPress sẽ dừng ngay lập tức và yêu cầu ban đầu sẽ không được gửi.

  • $rlà một loạt các đối số cho yêu cầu đó. Chúng ta phải thay đổi những điều này quá trong một phút.

  • $urllà - bất ngờ! - URL.

Vì vậy, trong cuộc gọi lại của t5_update_wp_per_https()chúng tôi, chúng tôi xem xét URL và nếu đó là một URL mà chúng tôi muốn lọc, chúng tôi nói KHÔNG với WordPress bằng cách không nói ra là không no false.

nhập mô tả hình ảnh ở đây

Lưu ý bên lề: Theo sau bạn có thể ngăn chặn tất cả các yêu cầu HTTP với:
add_filter( 'pre_http_request', '__return_true' );

Thay vào đó, chúng tôi thực hiện yêu cầu của riêng mình bằng một URL tốt hơn và các đối số được điều chỉnh một chút ( $r, được đổi tên thành để $argsdễ đọc).

Mật mã

Xin vui lòng đọc các ý kiến ​​nội tuyến, chúng là quan trọng.

<?php
/**
 * Plugin Name: T5 Update WP per HTTPS
 * Description: Forces update checks and downloads for WP to use HTTPS.
 * Plugin URI:  http://wordpress.stackexchange.com/questions/72529/filter-any-http-request-uri
 * Version:     2012.11.14
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * Licence:     MIT
 * License URI: http://opensource.org/licenses/MIT
 */

add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );

/**
 * Force HTTPS requests for update checks and new WP version downloads.
 *
 * @wp-hook pre_http_request
 * @param   bool   $false
 * @param   array  $args
 * @param   string $url
 * @return  FALSE|array|object FALSE if everything is okay, an array of request
 *                            results or an WP_Error instance.
 */
function t5_update_wp_per_https( $false, $args, $url )
{
    // Split the URL into useful parts.
    $url_data = parse_url( $url );

    // It is already HTTPS.
    if ( 'https' === strtolower( $url_data['scheme'] ) )
        return FALSE;

    // Not our host.
    if ( FALSE === stripos( $url_data['host'], 'wordpress.org' ) )
        return FALSE;

    // Make that an HTTPS request.
    $new_url = substr_replace( $url, 'https', 0, 4 );

    // WP_Http cannot verify the wordpress.org certificate.
    $args['sslverify'] = FALSE;

    // It is slow. We wait at least 30 seconds.
    30 > $args['timeout'] and $args['timeout'] = 30;

    // Get an instance of WP_Http.
    $http    = _wp_http_get_object();

    // Get the result.
    $result = $http->request( $new_url, $args );

    /* prepend this line with a '#' to debug like a boss.
    print '<pre>'
    . htmlspecialchars( print_r( $result, TRUE ), ENT_QUOTES, 'utf-8', FALSE )
    . '</pre>';
    die();
    /**/

    return $result;
}

Các bài kiểm tra

Không có plugin mà WordPress đã sử dụng:

  • http://api.wordpress.org/core/version-check/1.6/ để kiểm tra cập nhật và
  • http://wordpress.org/wordpress-3.4.2.zip để tải về các tập tin mới.

Tôi đã thử nghiệm nó với hai bản cài đặt tại địa phương, một trang web duy nhất và một thiết lập nhiều trang web trên Win 7. Để buộc một bộ cập nhật tôi $wp_versionwp-includes/version.phpđến 1và phiên bản của TwentyEleven tới 1.3.

Để xem lưu lượng mạng tôi đã sử dụng Wireshark : Nó miễn phí, nó chạy trên Windows và Linux và nó cung cấp một số công cụ lọc ấn tượng.

Việc xem HTTPS hơi khó khăn một chút: Rốt cuộc bạn cũng chỉ thấy dữ liệu được mã hóa. Để xem plugin của tôi đã làm những gì cần làm, trước tiên tôi đã xem lưu lượng không được mã hóa và lưu ý địa chỉ IP được sử dụng để kết nối với wordpress.org. Đó là 72.233.56.138, đôi khi 72.233.56.139.
Không có gì đáng ngạc nhiên, có một bộ cân bằng tải và có lẽ nhiều công cụ khác, vì vậy chúng tôi không thể dựa vào một địa chỉ IP.

Sau đó, tôi gõ ip.addr == 72.233.56.138vào mặt nạ bộ lọc, kích hoạt plugin, đi đến wp-admin/update-core.phpvà xem lưu lượng trong Wireshark. Các dòng màu xanh lá cây là các yêu cầu trong văn bản thuần túy - chính xác là những gì chúng ta không muốn. Các đường màu đỏ và đen là một dấu hiệu của sự thành công.

Dây đeo

Việc kiểm tra cập nhật diễn ra tốt đẹp: Nó tìm thấy các phiên bản mới hơn của Wikipedia. Các cập nhật thực tế cho chủ đề và cốt lõi cũng đi tốt. Chính xác những gì tôi cần.

Và vẫn có thể dễ dàng hơn nếu có một bộ lọc đơn giản cho URL.


1
+1 cho /* /**/, chỉ vì đó là thiên tài. Và (nếu tôi có thể) thêm +1 cho Charles Bronson. Và sau đó nên có thêm +1 để giải thích chi tiết, nhận xét & ảnh chụp màn hình.
kaiser

3
    add_filter('http_request_args', 'http_request_args_custom', 10,2);
    function http_request_args_custom($request,$url){
            if (strpos($url, 'wordpress.org') !== false){
                    global $replaced_url;
                    $replaced_url = 'http://wordpress.local';
            }
            return $request;
    }

    add_action('http_api_curl', 'http_api_curl_custom');
    function http_api_curl_custom(&$handle){
            global $replaced_url;
            if (!is_null($replaced_url))
                    curl_setopt( $handle, CURLOPT_URL, $replaced_url);
    }

    $http = new WP_Http();
    $response = $http->request('http://wordpress.org', array());

    var_dump($response);

1
Cần phải đề cập rằng, trong ví dụ mã này, trong hàm http_api_curl_custom, biến toàn cục $ thay_url nên được đặt thành NULL sau khi được sử dụng. Mặt khác, sau lần xuất hiện đầu tiên của "wordpress.org" trong url, tất cả các url khác sẽ được thay thế.
MihanEntalpo
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.