سؤال

في موقع الويب الخاص بي ، لدي برنامج نصي PHP يقوم بتشغيل تنزيل ملف دون إظهار المسار الكامل للملف ، يبدو الرمز مثل هذا:

$path = '../examples/test.zip';
$type = "application/zip";

header("Expires: 0");
header("Pragma: no-cache");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: pre-check=0, post-check=0, max-age=0');
header("Content-Description: File Transfer");
header("Content-Type: " . $type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");

readfile($path); // outputs the content of the file

exit();

هناك طريقة لإضافة مصادقة HTTP قبل إطلاق التنزيل؟

شكرا لك مقدما!


تحرير 1:بفضل André Hoffmann ، قمت بحل المشكلة باستخدام مصادقة HTTP الأساسية! ولكن إذا كنت أرغب في استخدام مصادقة HTTP Digest مثل ما يلي ، كيف يمكنني أن أفعل؟ لقد حاولت كتابة الكود أعلاه ، بعد السطر: "صدى" تم تسجيل الدخول على أنه: ". $ Data ['username'] ؛" ... لكنني أحصل على خطأ في القول إنه لا يمكنني تعديل الرأس مرتين!

<?php

$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}


// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');


// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response){
    die('Wrong Credentials!');
}

// ok, valid username & password
echo 'Your are logged in as: ' . $data['username'];


// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}

?>

المحلول:

بفضل أندريه وأنتوني ، يمكنني كتابة الحل:

<?php

$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}


// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');


// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response){
    die('Wrong Credentials!');
}

// ok, valid username & password ... start the download
$path = '../examples/test.zip';
$type = "application/zip";

header("Expires: 0");
header("Pragma: no-cache");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: pre-check=0, post-check=0, max-age=0');
header("Content-Description: File Transfer");
header("Content-Type: " . $type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");

readfile($path); // outputs the content of the file

exit();


// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}

?>
هل كانت مفيدة؟

المحلول

بالتأكيد انظر الدليل لهذا.

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
    //check $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW']
    if ($valid) {
        //start download

        $path = '../examples/test.zip';
        $type = "application/zip";

        header("Expires: 0");
        header("Pragma: no-cache");
        header('Cache-Control: no-store, no-cache, must-revalidate');
        header('Cache-Control: pre-check=0, post-check=0, max-age=0');
        header("Content-Description: File Transfer");
        header("Content-Type: " . $type);
        header("Content-Length: " .(string)(filesize($path)) );
        header('Content-Disposition: attachment; filename="'.basename($path).'"');
        header("Content-Transfer-Encoding: binary\n");

        readfile($path); // outputs the content of the file

        exit();
    } else {
        //show error
    }
}

تحديث:

A.HTACCESS المستندة إلى المصادقة تسمح باستخدام أكثر من مستخدم واحد. ضع هذا في .htaccess الخاص بك:

AuthType Basic
AuthName "Password Required"
AuthUserFile passwords.file
AuthGroupFile groups.file

الملف passwords.file يمكن إنشاء كلمات المرور باستخدام htpasswd الأداة التي جاءت مع أباتشي. الملف مجموعات يجب أن تشبه هذا:

GroupName: rbowen dpitts sungo rshersey

هنا يمكنك فقط سرد المستخدمين الذين يجب أن يتمكنوا من الوصول إلى الدليل.

من فضلك انظر أيضا هذه درس تعليمي.

نصائح أخرى

هل تحاول بدء التنزيل بعد وجود Script Echos "لقد قمت بتسجيل الدخول بنجاح ..."؟

لا يمكنك تعيين أي رؤوس بعد إخراج أي شيء لفحصه. بمجرد صدىك أو طباعتك أو ما لديك ، بدأت جزء الجسم من استجابة HTTP ، مما يعني أن الرؤوس قد تم تعيينها.

بالمناسبة ، إذا حاولت إعداد الرؤوس ثم إعطاء بت "قمت بتسجيل الدخول" ، فسيتعلق ذلك في الملف ، وليس الإخراج إلى الشاشة.

ما تريد القيام به هو هل لديك إخراج البرنامج النصي "أنت قمت بتسجيل الدخول" إعادة توجيه إلى البرنامج النصي الذي يرسل رؤوس التنزيل. لن يرى المستخدم تلك الصفحة الثانية ، حيث يتم تعيين الرأس على "المرفق". هذه هي الطريقة التي تعمل بها صفحات "التنزيل سوف تبدأ للحظات".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top