HTTP 인증 보호 폴더에서 로그 아웃 하는 올바른 방법 은 무엇입니까 ?
이것을 달성 할 수있는 해결 방법이 있지만 버그가 있거나 특정 상황 / 브라우저에서 작동하지 않기 때문에 잠재적으로 위험합니다. 그래서 나는 정확하고 깨끗한 해결책을 찾고 있습니다.
Miscellaneous -> Clear Private Data -> HTTP Authentication
HTTP 인증 보호 폴더에서 로그 아웃 하는 올바른 방법 은 무엇입니까 ?
이것을 달성 할 수있는 해결 방법이 있지만 버그가 있거나 특정 상황 / 브라우저에서 작동하지 않기 때문에 잠재적으로 위험합니다. 그래서 나는 정확하고 깨끗한 해결책을 찾고 있습니다.
Miscellaneous -> Clear Private Data -> HTTP Authentication
답변:
뮤 브라우저간에 일관된 방식이 아닌 올바른 방법은 없습니다.
이것은 HTTP 사양 (섹션 15.6) 에서 발생하는 문제입니다 .
기존 HTTP 클라이언트 및 사용자 에이전트는 일반적으로 인증 정보를 무기한 보유합니다. HTTP / 1.1. 서버가 클라이언트에게 이러한 캐시 된 자격 증명을 삭제하도록 지시하는 방법을 제공하지 않습니다.
반면에 10.4.2 절 은 다음과 같이 말합니다.
요청에 이미 인증 자격 증명이 포함 된 경우 401 응답은 해당 자격 증명에 대한 인증이 거부되었음을 나타냅니다. 401 응답에 이전 응답과 동일한 시도가 포함되어 있고 사용자 에이전트가 이미 한 번 이상 인증을 시도한 경우 응답에 제공된 엔티티가 사용자에게 표시되어야합니다. 해당 엔티티는 관련 진단 정보를 포함 할 수 있기 때문입니다.
즉, @Karsten이 말한 것처럼 로그인 상자를 다시 표시 할 수 는 있지만 브라우저는 요청을 존중할 필요가 없으므로이 (미스) 기능에 너무 의존하지 마십시오.
Safari에서 잘 작동하는 방법. Firefox 및 Opera에서도 작동하지만 경고가 표시됩니다.
Location: http://logout@yourserver.example.com/
이렇게하면 브라우저가 새 사용자 이름으로 URL을 열도록하여 이전 사용자 이름보다 우선합니다.
user:password@host
이 권장되지 않습니다. http://logout@yourserver.example.com/
대부분의 경우 에만 사용하는 것은 좋지 않으며 작동해야합니다.
간단한 대답은 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
따라서 자격 증명을 한 번 비활성화하면 사소한 것입니다.
"Password protected"라는 HTTP 기본 인증 영역이 있고 Bob이 로그인했다고 가정합니다. 로그 아웃하려면 2 개의 AJAX 요청을합니다.
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;
}
일반적으로 브라우저가 사용자에게 자격 증명을 요청하고이를 특정 웹 사이트에 제공 한 후에는 추가 프롬프트없이 계속 그렇게합니다. 클라이언트 측에서 쿠키를 지우는 다양한 방법과는 달리 브라우저에 제공된 인증 자격 증명을 잊어달라고 요청하는 비슷한 방법을 모르겠습니다.
Trac-기본적으로 HTTP 인증도 사용합니다. 로그 아웃이 작동하지 않으며 수정할 수 없습니다.
- 이것은 HTTP 인증 체계 자체의 문제이며, Trac에서 제대로 수정하기 위해 할 수있는 일은 없습니다.
- 현재 모든 주요 브라우저에서 작동하는 해결 방법 (JavaScript 또는 기타)이 없습니다.
보낸 사람 : http://trac.edgewall.org/ticket/791#comment:103
이 질문에 대한 실제 답변이없는 것처럼 보이며 7 년 전에 문제 가보고되었으며 HTTP는 상태가 없습니다. 인증 자격 증명을 사용하여 요청을 수행하거나 수행하지 않습니다. 그러나 그것은 서버가 아닌 클라이언트가 요청을 보내는 문제입니다. 서버는 요청 URI에 인증이 필요한지 여부 만 말할 수 있습니다.
.htaccess 인증을 재설정해야하므로 다음을 사용했습니다.
<?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;
}
?>
여기에서 찾았습니다 : http://php.net/manual/en/features.http-auth.php
그림을 이동.
Lynx는 다른 브라우저와 마찬가지로 인증을 지우지 않습니다.)
설치된 브라우저에서 테스트 한 후 닫히면 각 브라우저는 일관되게 다시 입력해야합니다.
WWW-Authenticate
문제가 발생하여 자동으로 로그 아웃 된 것을 제거합니다.
WWW-Authenticate
하나 개의 브라우저 (크롬)의 문제를 해결하면서하는 자격 증명을 기억하고 자동 재 로그인의 결과로, 다음 요청에 그들을 보내 다른 브라우저 (파이어 폭스)의 원인! 아아!
이것은 찾은 솔루션이 아닐 수도 있지만 다음과 같이 해결했습니다. 로그 아웃 프로세스를위한 2 개의 스크립트가 있습니다.
logout.php
<?php
header("Location: http://.@domain.com/log.php");
?>
log.php
<?php
header("location: https://google.com");
?>
이렇게하면 경고 메시지가 표시되지 않고 세션이 종료됩니다.
지금까지 찾은 가장 좋은 해결책은 (의사 코드의 일종이며, $isLoggedIn
http auth의 의사 변수입니다) :
"로그 아웃"할 때 사용자가 실제로 로그 아웃되었다는 정보를 세션에 저장하십시오.
function logout()
{
//$isLoggedIn = false; //This does not work (point of this question)
$_SESSION['logout'] = true;
}
인증을 확인하는 장소에서 조건을 확장합니다.
function isLoggedIn()
{
return $isLoggedIn && !$_SESSION['logout'];
}
세션은 http 인증 상태와 다소 연결되어 있으므로 사용자가 브라우저를 열어두고 브라우저에서 http 인증이 유지되는 한 로그 아웃 상태를 유지합니다.
어쩌면 내가 요점을 잃어 버렸을 수도 있습니다.
HTTP 인증을 종료하는 가장 확실한 방법은 브라우저와 모든 브라우저 창을 닫는 것입니다. Javascript를 사용하여 브라우저 창을 닫을 수는 있지만 모든 브라우저 창을 닫을 수는 없습니다.
여기에는 많은 복잡한 답변이 있습니다. 내 특별한 경우에는 로그 아웃에 대한 깨끗하고 간단한 수정 사항을 찾았습니다. 아직 Edge에서 테스트하지 않았습니다. 로그인 한 페이지에서 다음과 유사한 로그 아웃 링크를 배치했습니다.
<a href="https://MyDomainHere.net/logout.html">logout</a>
그리고 logout.html 페이지 (.htaccess로 보호됨)의 헤드에서 다음과 비슷한 페이지 새로 고침이 있습니다.
<meta http-equiv="Refresh" content="0; url=https://logout:logout@MyDomainHere.net/" />
사이트에 캐시 된 사용자 이름과 비밀번호를 지우려면 "로그 아웃"이라는 단어를 그대로 두십시오.
처음부터 여러 페이지를 직접 로그인 할 수 있어야한다면 각 진입 지점마다 해당 logout.html 페이지가 필요하다는 것을 인정합니다. 그렇지 않으면 실제 로그인 프롬프트 전에 프로세스에 추가 게이트 키퍼 단계를 도입하여 로그 아웃을 중앙 집중화 할 수 있으며, 로그인 대상에 문구를 입력해야합니다.