2010-09-27 60 views
6

Tôi đang viết bản thân mình một tập lệnh về cơ bản cho phép tôi gửi một URL và hai kích thước nguyên trong chuỗi truy vấn của một yêu cầu nhận đơn. Tôi đang sử dụng base64 để mã hóa nó, nhưng nó khá dài và tôi lo ngại rằng URL có thể quá lớn.PHP: Mã hóa ngắn/bị che khuất cho URL được nhúng trong một URL khác?

Có ai biết phương pháp làm việc thay thế, ngắn hơn không? Nó cần phải được giải mã-có thể khi nhận được trong một yêu cầu nhận được, vì vậy md5/sha1 là không thể.

Cảm ơn thời gian của bạn.


Sửa: Xin lỗi - Tôi nên đã giải thích tốt hơn: Ok, trên trang web của chúng tôi chúng tôi hiển thị ảnh chụp màn hình của trang web mà có được niêm yết công khai để xem xét. Chúng tôi có máy chủ hình thu nhỏ/ảnh chụp màn hình của riêng mình. Về cơ bản tôi sẽ có thẻ hình ảnh chứa một chuỗi được mã hóa lưu trữ URL để chụp ảnh màn hình và chiều rộng/chiều cao của hình ảnh hiển thị. Tuy nhiên tôi không muốn nó trong 'nguyên văn bản' cho thế giới để xem. Rõ ràng base64 có thể được quyết định bởi bất cứ ai, nhưng chúng tôi không muốn joe trung bình của bạn chọn lên đường dẫn URL. Thực sự tôi cần phải tìm nạp: url, chiều rộng, chiều cao trong một yêu cầu GET duy nhất.

+2

Có lý do cụ thể nào để không sử dụng POST hoặc Phiên thay thế không? Chúng phù hợp hơn nhiều để truyền khối dữ liệu có kích thước hợp lý giữa các trang –

+0

Không thực sự có thể sử dụng bài đăng (tôi nghĩ là anyway). Nó đang được sử dụng để có được một hình ảnh và kích thước của nó (mà là trong một mảng serialized bên trong chuỗi được mã hóa). Nó phải hoạt động với một thẻ tiêu chuẩn html . – Sk446

+0

Tôi đang bối rối. Bạn đang gửi hình ảnh từ máy chủ hoặc từ trình duyệt? –

Trả lời

3

URL không có nghĩa là gửi chuỗi dữ liệu dài, được mã hóa hoặc không được mã hóa. Sau một thời điểm nhất định, khi bạn đang xử lý một lượng lớn dữ liệu được gửi qua URL, bạn chỉ nên bắt đầu sử dụng POST hoặc một số hình thức lưu trữ cục bộ. FYI, IE có giới hạn URL là 2038 ký tự.


EDIT: Tôi không hiểu một điều. Tại sao bạn không lưu vào bộ nhớ đệm ảnh chụp màn hình? Có vẻ như rất tốn kém tài nguyên để chụp ảnh màn hình mới mỗi lần ai đó xem một trang có liên kết IMG đến url đó.

Có thể đối tượng của bạn nhỏ và tài nguyên không phải là vấn đề. Tuy nhiên, nếu nó là đối diện và trên thực tế nó là một trang web công cộng-đó sẽ không quy mô rất tốt. Tôi biết tôi sẽ vượt ra ngoài những gì câu hỏi ban đầu của bạn hỏi, nhưng điều này sẽ giải quyết câu hỏi của bạn và nhiều hơn nữa.

Ngay sau khi trang web được đăng lên, lưu trữ url trong một số loại lưu trữ cục bộ, tốt nhất là trong sql. Tôi sẽ tiếp tục ví dụ này như thể bạn chọn SQL, nhưng tất nhiên việc thực hiện của bạn là sự lựa chọn của bạn. Tôi sẽ có một khóa chính, trường url và dấu thời gian last_updated và tùy chọn đường dẫn hình thu nhỏ của hình ảnh.

Bằng cách sử dụng bộ nhớ cục bộ, bây giờ bạn có thể kéo hình ảnh ra khỏi bản sao được lưu trữ cục bộ trên máy chủ mỗi khi trang có hình thu nhỏ được yêu cầu. Một số lượng đáng kể tài nguyên được lưu và vì các trang web đó sẽ không được cập nhật thường xuyên, bạn có thể có một công việc cron hoặc một tập lệnh chạy mỗi khoảng thời gian x để làm mới các ảnh chụp màn hình trong toàn bộ cơ sở dữ liệu. Bây giờ, tất cả các bạn phải làm là liên kết trực tiếp (một lần nữa điều này phụ thuộc vào việc thực hiện của bạn) vào hình ảnh và không có công cụ chuỗi url lớn nào sẽ xảy ra.

OR, chỉ mất một cách dễ dàng và làm điều đó phía khách hàng với http://www.snap.com/

+0

REST-ish webservices với querystrings chắc chắn có thể thực hiện back-end và HTTP caching. Ví dụ. API biểu đồ của Google. –

+2

Đây là một cách tuyệt vời để không trả lời câu hỏi, được thực hiện tốt. – Deji

1

Chỉ cần đừng base64_encode($whole_file). Gửi nội dung theo khối và mã hóa các khối. Ngoài ra, nếu bạn phải biết số tiền lớn hơn của bạn có thể nhận được sau khi gọi tới số base64_encode(), số đó sẽ lớn hơn gấp đôi (nhưng nhỏ hơn 2.1*strlen($chunk))

+2

Tỷ lệ này thay vì 4/3 hoặc 4 · ceil (‌‍n/3) nếu bạn thêm dấu rãnh. – Gumbo

1

Bạn vẫn có thể sử dụng POST cho những gì bạn mô tả giả sử tôi đã hiểu chính xác, Tôi có thể không có.

Tôi đoán bạn đang làm một cái gì đó như thế này:

<a href="scripturl?w=11&h=100&url=really-long-secret-base64"> 
    <img src="imgurl"> 
</a> 

thay vì làm một cái gì đó như thế này:

<form method="POST" action="scripturl"> 
    <input type="hidden" name="width" value="100"> 
    <input type="hidden" name="height" value="100"> 
    <input type="hidden" name="url" value="secret-url-string-here"> 
    <input type="image" src="imgurl" name="submit"> 
</form> 
0

là kịch bản mà tạo ra các URL chạy trên một máy chủ khác nhau từ kịch bản diễn giải chúng? Nếu chúng ở trên cùng một máy chủ, cách tiếp cận rõ ràng sẽ là lưu trữ URL, chiều rộng và chiều cao mục tiêu trong cơ sở dữ liệu và chỉ cần chuyển một số nhận dạng bản ghi được tạo ngẫu nhiên trong chuỗi truy vấn.

5

Vì bạn chỉ sử dụng base64 để làm xáo trộn chuỗi, bạn chỉ có thể làm xáo trộn nó bằng thứ gì đó khác, như rot13 (hoặc chức năng thay thế chữ cái đơn giản của riêng bạn). Vì vậy, urlencode(str_rot13($str)) để mã hóa và str_rot13(urldecode($str)) để giải mã. Bạn có thể nén chuỗi trước khi mã hóa base64: base64_encode(gzencode($str, 9))gzdecode(base64_decode($str)) để giải mã. Hoặc, nếu đây chủ yếu là vấn đề bảo mật (bạn không nhớ mọi người nhìn thấy URL, bạn chỉ muốn ngăn mọi người hack nó), bạn có thể chuyển các tham số này với các biến chuỗi truy vấn bình thường, nhưng với một băm được nối vào ngăn chặn giả mạo. ví dụ:

function getHash($url, $width, $height) { 
    $secret = 'abcdefghijklmnopqrstuvwxyz whatever you want etc.'; 
    return sha1($url . $width . $height . $secret); 
} 

// So use this hash to to construct your URL querystring: 
$hash = getHash($url, $width, $height); 
$urlQuerystring = '?url='.urlencode($url).'&width='.(int) $width. 
        '&height='.(int) $height.'&hash='.$hash; 

// Then in your code that processes the URL, check the hash first 
if ($hash != getHash($url, $width, $height)) 
    // URL is invalid 

(Tắt chủ đề:. Mọi người đang nói rằng bạn nên sử dụng POST thay vì GET Nếu tất cả các URL đang làm là lấy ảnh chụp màn hình từ cơ sở dữ liệu của bạn để hiển thị (ví dụ một tra cứu tìm kiếm), sau đó GET là tốt và Nhưng nếu gọi những URL này thực sự đang thực hiện một hành động như truy cập vào một trang web khác, tạo và lưu trữ ảnh chụp màn hình, thì đó là POST, như tên của chúng cho thấy, GET là để truy xuất, POST là để gửi dữ liệu. NHẬN một hoạt động đắt tiền như tạo ảnh chụp màn hình, bạn có thể kết thúc việc sử dụng trang web của riêng mình khi Google vv lập chỉ mục các URL này.)

2

Có vẻ như mục tiêu của bạn là 1. để làm mờ một URL một cách trực quan và 2. để thường mã hóa dữ liệu gọn gàng để sử dụng trong URL.

Trước tiên, chúng tôi cần che khuất URL. Vì URL sử dụng nhiều từ điển Base64, bất kỳ mã hóa nào tạo ra nhị phân (mà sau đó phải là Base64-ed) sẽ có khả năng tăng kích thước. Tốt nhất là giữ từ điển trong phạm vi an toàn của URL với nhu cầu tối thiểu để thoát khi áp dụng urlencode(). I E. bạn muốn điều này:

/** 
* Rot35 for URLs. To avoid increasing size during urlencode(), commonly encoded 
* chars are mapped to more rarely used chars (end of the uppercase alpha). 
* 
* @param string $url 
* @return string 
*/ 
function rotUrl($url) { 
    return strtr($url, 
     'abcdefghijklmnopqrstuvwxyz0-:/?=&%#123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
     '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0-:/?=&%#'); 
} 

Bây giờ, để tiết kiệm byte, chúng ta có thể mã hóa các giản đồ URL vào một char (nói, h cho HTTP, H cho HTTPS), và chuyển đổi kích thước thành cơ sở 32. Bao bì này lên:

function obscure($width, $height, $url) { 
    $dimensions = base_convert($width, 10, 32) . "." 
       . base_convert($height, 10, 32) . "."; 
    preg_match('@^(https?)://(.+)@', $url, $m); 
    return $dimensions . (($m[1] === 'http') ? 'h' : 'H') . rotUrl($m[2]); 
} 

function unobscure($str) { /* exercise for the reader! */ } 

$url = 'https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=Base64'; 
$obs = obscure(550, 300, $url); 
// h6.9c.H5E.N9B9G5491.FI7UNU9E45O.G8GVK9KC5W-G5391CYcj-51I38XJ51I38Wk1J5fd 

Vì chúng ta tránh chars phi URL-an toàn, nếu điều này được đặt trong một chuỗi truy vấn (với urlencode), nó không phát triển nhiều (trong trường hợp này không phải ở tất cả).

Ngoài ra, bạn có thể muốn ký chuỗi này để những người biết mã hóa vẫn không thể chỉ định tham số riêng của họ thông qua URL. Đối với điều này, bạn sẽ sử dụng HMAC và mã hóa Base64URL băm. Bạn cũng có thể chỉ giữ một chuỗi con của hàm băm (~ 6 bit cho mỗi ký tự) để tiết kiệm không gian.sign() (dưới đây) cho biết thêm 8 nhân vật MAC (48 bit của băm lúc 6 bit/char):

function sign($key, $data) { 
    return $data . _hmac($key, $data, 8); 
} 
function verify($key, $signed) { 
    $mac = substr($signed, -8); 
    $data = substr($signed, 0, -8); 
    return $mac === _hmac($key, $data, 8) ? $data : false; 
} 
function _hmac($key, $data, $macLength) { 
    $mac = substr(base64_encode(hash_hmac('sha256', $data, $key, true)), 0, $macLength); 
    return strtr($mac, '+/', '-_'); // for URL 
} 

$key = "Hello World!"; 
$signed = sign($key, $obs); // appends MAC: "w-jjw2Wm" 

$obs = verify($key, $signed); // strips MAC and returns valid data, or FALSE 

Cập nhật: a tốt hơn RotURL function.

+0

Đây là 'câu trả lời' duy nhất tại đây. Các câu trả lời khác cố định về an ninh mà người hỏi cụ thể nói không quan trọng, hoặc chỉ cố gắng tranh luận chống lại câu hỏi đó. Câu trả lời này, tuy nhiên, rất hữu ích cho những người tìm kiếm câu hỏi cụ thể này. – Deji