HTTP 인증 보호 폴더에서 로그 아웃 하는 올바른 방법 은 무엇입니까 ?
이것을 달성 할 수있는 해결 방법이 있지만 버그가 있거나 특정 상황 / 브라우저에서 작동하지 않기 때문에 잠재적으로 위험합니다. 그래서 나는 정확하고 깨끗한 해결책을 찾고 있습니다.
답변
뮤 브라우저간에 일관된 방식이 아닌 올바른 방법은 없습니다.
이것은 HTTP 사양 (섹션 15.6) 에서 발생하는 문제입니다 .
기존 HTTP 클라이언트 및 사용자 에이전트는 일반적으로 인증 정보를 무기한 보유합니다. HTTP / 1.1. 서버가 클라이언트에게 이러한 캐시 된 자격 증명을 삭제하도록 지시하는 방법을 제공하지 않습니다.
반면에 10.4.2 절 은 다음과 같이 말합니다.
요청에 이미 인증 자격 증명이 포함 된 경우 401 응답은 해당 자격 증명에 대한 인증이 거부되었음을 나타냅니다. 401 응답에 이전 응답과 동일한 시도가 포함되어 있고 사용자 에이전트가 이미 한 번 이상 인증을 시도한 경우 응답에 제공된 엔티티가 사용자에게 표시되어야합니다. 해당 엔티티는 관련 진단 정보를 포함 할 수 있기 때문입니다.
즉, @Karsten이 말한 것처럼 로그인 상자를 다시 표시 할 수 는 있지만 브라우저는 요청을 존중할 필요가 없으므로이 (미스) 기능에 너무 의존하지 마십시오.
답변
Safari에서 잘 작동하는 방법. Firefox 및 Opera에서도 작동하지만 경고가 표시됩니다.
Location: http://logout@yourserver.example.com/
이렇게하면 브라우저가 새 사용자 이름으로 URL을 열도록하여 이전 사용자 이름보다 우선합니다.
답변
간단한 대답은 http 인증에서 안정적으로 로그 아웃 할 수 없다는 것입니다.
긴 대답 :
Http-auth (HTTP 사양의 나머지 부분과 마찬가지로)는 stateless입니다. 따라서 “로그인”또는 “로그 아웃”은 실제로 의미가있는 개념이 아닙니다. 이를 확인하는 가장 좋은 방법은 각 HTTP 요청에 대해 요청하는 것입니다 (그리고 페이지로드는 일반적으로 여러 요청임을 기억하십시오). “요청한 작업을 수행 할 수 있습니까?” 서버는 각 요청을 새로운 요청으로 간주하며 이전 요청과 관련이 없습니다.
브라우저는 처음 401에서 제공 한 자격 증명을 기억하고 후속 요청에 대한 사용자의 명시적인 권한없이 다시 전송하도록 선택했습니다. 이는 사용자에게 “로그인 / 로그 아웃”모델을 제공하려는 시도이지만 순전히 실패입니다. 이 상태 지속성을 시뮬레이션 하는 브라우저 입니다. 웹 서버는 완전히 알지 못합니다.
따라서 http-auth와 관련하여 “로그 아웃”은 순전히 브라우저가 제공하는 시뮬레이션이며 서버 권한 외부에 있습니다.
그렇습니다. 그러나 그들은 RESTful-ness (당신에게 가치가있는 경우)를 깨뜨리고 신뢰할 수 없습니다.
사이트 인증을 위해 로그인 / 로그 아웃 된 모델이 절대적으로 필요한 경우 가장 좋은 방법은 추적 쿠키이며 서버에 상태가 지속되는 방식 (mysql, sqlite, flatfile 등)을 유지하는 추적 쿠키입니다. 이를 위해서는 모든 요청을 예를 들어 PHP로 평가해야합니다.
답변
해결 방법
Javascript를 사용하여이 작업을 수행 할 수 있습니다.
<html><head>
<script type="text/javascript">
function logout() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject) {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (window.ActiveXObject) {
// IE clear HTTP Authentication
document.execCommand("ClearAuthenticationCache");
window.location.href='/where/to/redirect';
} else {
xmlhttp.open("GET", '/path/that/will/return/200/OK', true, "logout", "logout");
xmlhttp.send("");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {window.location.href='/where/to/redirect';}
}
}
return false;
}
</script>
</head>
<body>
<a href="#" onclick="logout();">Log out</a>
</body>
</html>
위에서 수행 한 작업은 다음과 같습니다.
-
IE의 경우 -인증 캐시를 지우고 어딘가에 리디렉션하십시오.
-
다른 브라우저의 경우 – ‘로그 아웃’로그인 이름과 비밀번호를 사용하여 XMLHttpRequest를이면에서 보냅니다. 요청에 200 OK를 반환하는 경로로 보내야합니다 (즉, HTTP 인증이 필요하지 않음).
교체 '/where/to/redirect'
로그 아웃 한 후 리디렉션 및 대체 어떤 경로로 '/path/that/will/return/200/OK'
200 OK를 반환합니다 귀하의 사이트에 대한 몇 가지 경로.
답변
해결 방법 (깨끗하고 훌륭하지 않거나 심지어 작동합니다! 의견 참조) 솔루션 :
자격 증명을 한 번 비활성화하십시오.
적절한 헤더를 보내서 HTTP 인증 로직을 PHP로 옮길 수 있습니다 (로그인하지 않은 경우).
Header('WWW-Authenticate: Basic realm="protected area"');
Header('HTTP/1.0 401 Unauthorized');
그리고 입력을 다음과 같이 파싱합니다.
$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW'] // httpauth-password
따라서 자격 증명을 한 번 비활성화하면 사소한 것입니다.
답변
두 단계로 HTTP 기본 인증에서 로그 아웃
“Password protected”라는 HTTP 기본 인증 영역이 있고 Bob이 로그인했다고 가정합니다. 로그 아웃하려면 2 개의 AJAX 요청을합니다.
- 액세스 스크립트 / logout_step1. .htusers에 임의의 임시 사용자를 추가하고 로그인 및 비밀번호로 응답합니다.
- 액세스 스크립트 / logout_step2 임시 사용자의 로그인과 암호로 인증 . 스크립트는 임시 사용자를 삭제하고 응답에이 헤더를 추가합니다.
WWW-Authenticate: Basic realm="Password protected"
이 시점에서 브라우저는 Bob의 자격 증명을 잊었습니다.
답변
문제에 대한 나의 해결책은 다음과 같습니다. 당신은 기능을 찾을 수 있습니다 http_digest_parse
, $realm
그리고 $users
이 페이지의 두 번째 예 : http://php.net/manual/en/features.http-auth.php .
session_start();
function LogOut() {
session_destroy();
session_unset($_SESSION['session_id']);
session_unset($_SESSION['logged']);
header("Location: /", TRUE, 301);
}
function Login(){
global $realm;
if (empty($_SESSION['session_id'])) {
session_regenerate_id();
$_SESSION['session_id'] = session_id();
}
if (!IsAuthenticated()) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$_SESSION['session_id'].'",opaque="'.md5($realm).'"');
$_SESSION['logged'] = False;
die('Access denied.');
}
$_SESSION['logged'] = True;
}
function IsAuthenticated(){
global $realm;
global $users;
if (empty($_SERVER['PHP_AUTH_DIGEST']))
return False;
// check PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
return False;// invalid username
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
// Give session id instead of data['nonce']
$valid_response = md5($A1.':'.$_SESSION['session_id'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response)
return False;
return True;
}