2009-10-10 2 views
1

나는 코드는 다음과 같이 파일의 전체 경로를 표시하지 않고 파일 다운로드를 시작 PHP 스크립트를보고했습니다HTTP 파일 다운로드를 인증하는 방법은 무엇입니까? 내 웹 사이트에서

$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 : 앙드레 호프만에 덕분에, 나는 HTTP 기본 인증을 사용하여 문제를 해결했습니다! 하지만 다음과 같은 HTTP 다이제스트 인증을 사용하려면 어떻게해야합니까? 위의 코드를 작성하려고 시도했습니다. "echo '당신은 다음과 같이 로그인되었습니다 :'; $ 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; 
} 

?> 
+0

HTTP 인증 인 imho는 HTTP 설정, 즉 Apache 설정 파일 또는 .htaccess 파일에서 수행되어야합니다. 이것이 보안의 추가 수준입니까, 아니면 PHP에서이 모든 것을하려고합니까? – Anthony

+0

나는 그 모든 것을 PHP로하려고하고있다. 왜냐하면 더 많은 한 사용자가 로그인 할 수 있어야하고 .htaccess를 통해 MySQL 데이터베이스에 액세스하는 방법을 모른다. – BitDrink

+0

'mod_auth_mysql' – Anthony

답변

1

물론 이것에 대한 the manual를 참조하십시오.

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

UPDATE는 :

같은 .htaccess 기반 인증 acutally 하나 이상의 사용자에 의해 사용되도록한다. 당신의 .htaccess이 넣어 :

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

파일 아파치와 함께 제공된 htpasswd 도구를 사용하여 만들 수있는 암호를 포함 passwords.file. 파일 groups.file이 유사 좋아한다 :

여기
GroupName: rbowen dpitts sungo rshersey 

당신은 기본적으로 그냥 디렉토리에 대한 액세스 권한이있는 사용자를 나열합니다.

this 자습서를 참조하십시오.

+0

고마워요! HTTP 다이제스트 인증을 사용하기 전에 헤더를 두 번 수정할 수 없다는 오류 메시지가 나타납니다. – BitDrink

+0

다시 한 번 감사드립니다. André! 나는 아직도 배울 것이 많다. .. 매우 감사한다! – BitDrink

1

"사용자가 성공적으로 로그인했습니다 ..."라는 메시지가 나타나면 다운로드를 시작 하시겠습니까?

화면에 아무 것도 출력하지 않으면 헤더를 설정할 수 없습니다. 에코 나 프린트 또는 what-have-you를 사용하면 HTTP 응답의 본문 부분을 시작 했으므로 헤더가 설정되었습니다.

그런데 헤더를 설정하고 "로그인했습니다"라는 비트를 지정하면 파일에 멈추어 화면에 출력되지 않습니다.

원하는 것은 스크립트 출력에 "사용자가 로그인했습니다"이며 은 다운로드 헤더를 보내는 스크립트에을 리디렉션합니다.헤더는 "첨부 파일"로 설정되므로 사용자는 두 번째 페이지를 보지 못합니다. 이것이 일반적인 "귀하의 다운로드가 잠시 시작됩니다"페이지가 작동하는 방식입니다.

+0

당신은 맞습니다! 감사! – BitDrink

관련 문제