Pregunta

En mi página web Tengo un script PHP que lanza una descarga de archivos sin mostrar la ruta completa del archivo, el código de este aspecto:

$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();

Hay una manera de añadir una autenticación HTTP antes de poner en marcha la descarga?

Gracias de antemano!


EDIT 1: Gracias a André Hoffmann, he resuelto el problema mediante el uso de una autenticación básica HTTP! Pero si me gustaría utilizar un HTTP Digest autenticación como la siguiente, ¿cómo puedo hacer? He tratado de escribir el código anterior, después de la línea: "eco 'Tu iniciado sesión como:' $ data [ 'username'];". ... pero me da un error diciendo que no puedo modificar el encabezado dos veces!

<?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;
}

?>

SOLUCIÓN:

Gracias a André y Anthony, puedo escribir la solución:

<?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;
}

?>
¿Fue útil?

Solución

la manual para esto.

<?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
    }
}

Actualizar

A la autenticación basada .htaccess acutally permite ser utilizado por más de un usuario. Poner esto en tu .htaccess:

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

El archivo passwords.file que contiene las contraseñas pueden ser creadas usando la herramienta htpasswd que viene con Apache. El archivo groups.file gustaría similar a esto:

GroupName: rbowen dpitts sungo rshersey

Aquí, básicamente, sólo una lista de los usuarios que deben tener acceso al directorio.

Por favor, consulta este tutorial.

Otros consejos

¿Estás tratando de iniciar la descarga, después de haber ecos del guión "Usted ha entrado con éxito en tan ..."?

No se puede establecer ninguna cabecera después de que haya nada de salida a la pantalla. Tan pronto como eco o de impresión o lo que usted quiera, que haya comenzado la parte del cuerpo de la respuesta HTTP, lo que significa que las cabeceras se han establecido.

Por cierto, si se intenta establecer las cabeceras y luego dando la "que ha entrado en el sistema" bits, que se quedan atascados en el archivo, no se emiten a la pantalla.

Lo que se quiere hacer es tener la salida del script "que está en el sistema" y el redireccionamiento a la secuencia de comandos que envía las cabeceras de descarga. El usuario no verá que la segunda página, como el encabezado se establece en "archivo adjunto". Así es como el típico "Su descarga comenzará momentáneamente" páginas funcionan.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top