기본 인증을 사용하여 웹 사이트에서 사용자 로그인하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/233507

문제

기본 인증을 사용하는 경우 웹 사이트에서 사용자를 로그 아웃 할 수 있습니까?

사용자가 인증되면 각 요청에는 로그인 정보가 포함되어 있으므로 다음에 동일한 자격 증명을 사용하여 사이트에 액세스 할 때 사용자가 자동으로 로그인되므로 킬링 세션은 충분하지 않습니다.

지금까지 유일한 솔루션은 브라우저를 닫는 것이지만 유용성 관점에서 허용되지는 않습니다.

도움이 되었습니까?

해결책

기본 인증은 로그 아웃을 관리하도록 설계되지 않았습니다. 당신은 그것을 할 수 있지만 완전히 자동으로는 아닙니다.

당신이해야 할 일은 사용자에게 로그 아웃 링크를 클릭하고 동일한 영역과 동일한 URL 폴더 레벨에서 로그인을 요청하는 것을 보내는 '401 무단'을 보내도록하는 것입니다.

다음은 잘못된 자격 증명을 입력하도록 지시해야합니다. 빈 사용자 이름과 통과 단어와 응답으로 "성공적으로 로그 아웃했습니다"페이지를 다시 보냅니다. 잘못/공백 자격 증명은 이전 올바른 자격 증명을 덮어 씁니다.

요컨대, 로그 아웃 스크립트는 로그인 스크립트의 논리를 반전시키고 사용자가 성공한 경우에만 성공 페이지를 반환합니다. 그렇지 않습니다 올바른 자격 증명을 전달합니다.

문제는 "비밀번호를 입력하지 마십시오"비밀번호 상자가 사용자 수락을 충족시키는 다소 궁금한 점이 있는지 여부입니다. 비밀번호를 자동 채우려는 비밀번호 관리자도 여기에 방해가 될 수 있습니다.

주석에 대한 응답으로 추가하도록 편집 : Re-Log-In은 약간 다른 문제입니다 (2 단계 로그 아웃/로그인이 필요하지 않은 한). 두 번째 (아마도 다른 사용자 이름/비밀번호를 가지고 있음)를 수락하는 것보다 Relogin 링크에 액세스하려는 첫 번째 시도를 거부해야합니다 (401). 이 작업을 수행 할 수있는 몇 가지 방법이 있습니다. 하나는 로그 아웃 링크 (예 : /relogin? username)에 현재 사용자 이름을 포함시키고 자격 증명이 사용자 이름과 일치하는시기를 거부하는 것입니다.

다른 팁

Bobince의 답변에 추가 ...

Ajax를 사용하면 '로그 아웃'링크/버튼을 JavaScript 기능에 연결할 수 있습니다. 이 기능이 XMLHTTpRequest를 잘못 사용자 이름과 비밀번호로 보내도록하십시오. 이렇게하면 401이 되돌아 가야합니다. 그런 다음 문서를 사전 로그 인 페이지로 다시 설정하십시오. 이런 식으로 사용자는 로그 아웃 중에 추가 로그인 대화 상자를 보지 못하거나 나쁜 자격 증명을 입력해야합니다.

사용자가 링크를 클릭하도록합니다 https : // log : out@example.com/. 그것은 유효하지 않은 자격 증명으로 기존 자격 증명을 덮어 쓸 것입니다. 로그 아웃.

전적으로 JavaScript로 할 수 있습니다.

즉 기본 인증 캐시를 지우기위한 (오랫동안) 표준 API를 가지고 있습니다.

document.execCommand("ClearAuthenticationCache")

작동 할 때 True를 반환해야합니다. 거짓, 정의되지 않은 또는 다른 브라우저에서 날려 버립니다.

새로운 브라우저 (2012 년 12 월 현재 : Chrome, Firefox, Safari)에는 "마법"동작이 있습니다. 그들이 a를 본다면 성공적인 가짜가있는 기본 인증 요청 (다른 사용자 이름) logout) 자격 증명 캐시를 지우고 새로운 가짜 사용자 이름에 대해 설정했을 가능성이 있습니다.이 이름은 콘텐츠를보기에 유효한 사용자 이름이 아닌지 확인해야합니다.

그 기본 예는 다음과 같습니다.

var p = window.location.protocol + '//'
// current location must return 200 OK for this GET
window.location = window.location.href.replace(p, p + 'logout:password@')

위의 "비동기"방법은 logout 사용자 이름. 예시:

(function(safeLocation){
    var outcome, u, m = "You should be logged out now.";
    // IE has a simple solution for it - API:
    try { outcome = document.execCommand("ClearAuthenticationCache") }catch(e){}
    // Other browsers need a larger solution - AJAX call with special user name - 'logout'.
    if (!outcome) {
        // Let's create an xmlhttp object
        outcome = (function(x){
            if (x) {
                // the reason we use "random" value for password is 
                // that browsers cache requests. changing
                // password effectively behaves like cache-busing.
                x.open("HEAD", safeLocation || location.href, true, "logout", (new Date()).getTime().toString())
                x.send("")
                // x.abort()
                return 1 // this is **speculative** "We are done." 
            } else {
                return
            }
        })(window.XMLHttpRequest ? new window.XMLHttpRequest() : ( window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : u ))
    }
    if (!outcome) {
        m = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser."
    }
    alert(m)
    // return !!outcome
})(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)

북마크로 만들 수도 있습니다.

javascript:(function(c){var a,b="You should be logged out now.";try{a=document.execCommand("ClearAuthenticationCache")}catch(d){}a||((a=window.XMLHttpRequest?new window.XMLHttpRequest:window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):void 0)?(a.open("HEAD",c||location.href,!0,"logout",(new Date).getTime().toString()),a.send(""),a=1):a=void 0);a||(b="Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser.");alert(b)})(/*pass safeLocation here if you need*/);

다음 함수는 Firefox 40, Chrome 44, Opera 31 및 IE 11에서 작동하는 것으로 확인됩니다.
Bowser 브라우저 감지에 사용되며 jQuery도 사용됩니다.

-SecURL은 로그 아웃 할 암호 보호 영역의 URL입니다.
-Redirurl은 비 암호 보호 영역 (로그 아웃 성공 페이지)의 URL입니다.
- 리디렉션 타이머 (현재 200ms)를 늘릴 수 있습니다.

function logout(secUrl, redirUrl) {
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", secUrl, true);
        xmlhttp.setRequestHeader("Authorization", "Basic logout");
        xmlhttp.send();
    } else {
        alert("Logging out automatically is unsupported for " + bowser.name
            + "\nYou must close the browser to log out.");
    }
    setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);
}

이것은 기본 승인으로 직접 불가능합니다.

서버가 브라우저에 사용자가 이미 제시 한 자격 증명을 보내도록 지시하는 HTTP 사양에 메커니즘이 없습니다.

일반적으로 xmlhttprequest를 사용하여 원래 제공된 자격 증명이있는 HTTP 요청을 보내기 위해 "해킹"(기타 답변 참조)이 있습니다.

jQuery를 사용하는 매우 간단한 JavaScript 예는 다음과 같습니다.

function logout(to_url) {
    var out = window.location.href.replace(/:\/\//, '://log:out@');

    jQuery.get(out).error(function() {
        window.location = to_url;
    });
}

이 로그 사용자가 브라우저 로그인 상자를 다시 표시하지 않고 A로 다시 리디렉션합니다. 로그 아웃 페이지

실제로 매우 간단합니다.

브라우저에서 다음을 방문하고 잘못된 자격 증명을 사용하십시오.http : // username : password@yourdomain.com

"로그 아웃"해야합니다.

이것은 IE/Netscape/Chrome에서 작동합니다.

      function ClearAuthentication(LogOffPage) 
  {
     var IsInternetExplorer = false;    

     try
     {
         var agt=navigator.userAgent.toLowerCase();
         if (agt.indexOf("msie") != -1) { IsInternetExplorer = true; }
     }
     catch(e)
     {
         IsInternetExplorer = false;    
     };

     if (IsInternetExplorer) 
     {
        // Logoff Internet Explorer
        document.execCommand("ClearAuthenticationCache");
        window.location = LogOffPage;
     }
     else 
     {
        // Logoff every other browsers
    $.ajax({
         username: 'unknown',
         password: 'WrongPassword',
             url: './cgi-bin/PrimoCgi',
         type: 'GET',
         beforeSend: function(xhr)
                 {
            xhr.setRequestHeader("Authorization", "Basic AAAAAAAAAAAAAAAAAAA=");
         },

                 error: function(err)
                 {
                    window.location = LogOffPage;
             }
    });
     }
  }


  $(document).ready(function () 
  {
      $('#Btn1').click(function () 
      {
         // Call Clear Authentication 
         ClearAuthentication("force_logout.html"); 
      });
  });          
function logout() {
  var userAgent = navigator.userAgent.toLowerCase();

  if (userAgent.indexOf("msie") != -1) {
    document.execCommand("ClearAuthenticationCache", false);
  }

  xhr_objectCarte = null;

  if(window.XMLHttpRequest)
    xhr_object = new XMLHttpRequest();
  else if(window.ActiveXObject)
    xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
  else
    alert ("Your browser doesn't support XMLHTTPREQUEST");

  xhr_object.open ('GET', 'http://yourserver.com/rep/index.php', false, 'username', 'password');
  xhr_object.send ("");
  xhr_object = null;

  document.location = 'http://yourserver.com'; 
  return false;
}
 function logout(url){
    var str = url.replace("http://", "http://" + new Date().getTime() + "@");
    var xmlhttp;
    if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest();
    else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4) location.reload();
    }
    xmlhttp.open("GET",str,true);
    xmlhttp.setRequestHeader("Authorization","Basic xxxxxxxxxx")
    xmlhttp.send();
    return false;
}

필요한 것은 일부 로그 아웃 URL에서 사용자를 리디렉션하고 반환하기 만하면됩니다. 401 Unauthorized 그것에 오류. 오류 페이지 (기본 인증없이 액세스 할 수 있어야 함)에서 홈페이지에 대한 전체 링크 (체계 및 호스트 이름 포함)를 제공해야합니다. 사용자는이 링크를 클릭하면 브라우저가 자격 증명을 다시 요청합니다.

nginx의 예 :

location /logout {
    return 401;
}

error_page 401 /errors/401.html;

location /errors {
    auth_basic off;
    ssi        on;
    ssi_types  text/html;
    alias /home/user/errors;
}

오류 페이지 /home/user/errors/401.html:

<!DOCTYPE html>
<p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>

이 JavaScript는 모든 최신 버전 브라우저에서 작동해야합니다.

//Detect Browser
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var Host = window.location.host;


//Clear Basic Realm Authentication
if(isIE){
//IE
    document.execCommand("ClearAuthenticationCache");
    window.location = '/';
}
else if(isSafari)
{//Safari. but this works mostly on all browser except chrome
    (function(safeLocation){
        var outcome, u, m = "You should be logged out now.";
        // IE has a simple solution for it - API:
        try { outcome = document.execCommand("ClearAuthenticationCache") }catch(e){}
        // Other browsers need a larger solution - AJAX call with special user name - 'logout'.
        if (!outcome) {
            // Let's create an xmlhttp object
            outcome = (function(x){
                if (x) {
                    // the reason we use "random" value for password is 
                    // that browsers cache requests. changing
                    // password effectively behaves like cache-busing.
                    x.open("HEAD", safeLocation || location.href, true, "logout", (new Date()).getTime().toString())
                    x.send("");
                    // x.abort()
                    return 1 // this is **speculative** "We are done." 
                } else {
                    return
                }
            })(window.XMLHttpRequest ? new window.XMLHttpRequest() : ( window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : u )) 
        }
        if (!outcome) {
            m = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser."
        }
        alert(m);
        window.location = '/';
        // return !!outcome
    })(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)
}
else{
//Firefox,Chrome
    window.location = 'http://log:out@'+Host+'/';
}

응용 프로그램에 이것을 추가하십시오.

@app.route('/logout')
def logout():
    return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})

위에서 읽은 내용을 기반으로 모든 브라우저에서 작동하는 간단한 솔루션을 얻었습니다.

1) 로그 아웃 페이지에서 로그인 백엔드에 Ajax를 호출합니다. 로그인 백엔드는 로그 아웃 사용자를 허용해야합니다. 백엔드가 수락되면 브라우저는 현재 사용자를 지우고 "로그 아웃"사용자를 가정합니다.

$.ajax({
    async: false,
    url: 'http://your_login_backend',
    type: 'GET',
    username: 'logout'
});      

setTimeout(function () {
    window.location.href = 'http://normal_index';
}, 200);

2) 이제 사용자가 일반 색인 파일로 돌아 왔을 때 사용자 "로그 아웃"과 함께 시스템을 자동 입력하려고 시도합니다.이 두 번째로 401로 답장하여 로그인/비밀번호 대화 상자를 호출해야합니다.

3) 그렇게하는 방법에는 여러 가지가 있습니다. 로그인 백쪽 끝 두 가지를 만들었습니다. 하나는 로그 아웃 사용자를 받아들이는 것과 그렇지 않은 경우. 내 일반 로그인 페이지는 허용되지 않는 페이지를 사용하고 로그 아웃 페이지는 그것을 받아들이는 페이지를 사용합니다.

  • 세션 ID (쿠키) 사용
  • 서버에서 세션 ID를 무효화하십시오
  • 잘못된 세션 ID를 가진 사용자를 허용하지 마십시오

최신 크롬 버전에 대한 Mthoring의 솔루션을 업데이트했습니다.

function logout(secUrl, redirUrl) {
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit || bowser.chrome) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open(\"GET\", secUrl, true);
        xmlhttp.setRequestHeader(\"Authorization\", \"Basic logout\");\
        xmlhttp.send();
    } else {
// http://stackoverflow.com/questions/5957822/how-to-clear-basic-authentication-details-in-chrome
        redirUrl = url.replace('http://', 'http://' + new Date().getTime() + '@');
    }
    setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);
}
    function logout(secUrl, redirUrl) {
        if (bowser.msie) {
            document.execCommand('ClearAuthenticationCache', 'false');
        } else if (bowser.gecko) {
            $.ajax({
                async: false,
                url: secUrl,
                type: 'GET',
                username: 'logout'
            });
        } else if (bowser.webkit) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", secUrl, true);
            xmlhttp.setRequestHeader("Authorization", "Basic logout");
            xmlhttp.send();
        } else {
            alert("Logging out automatically is unsupported for " + bowser.name
                + "\nYou must close the browser to log out.");
        }
        setTimeout(function () {
            window.location.href = redirUrl;
        }, 200);
    }

위의 방법을 다음 방법으로 사용해 보았습니다.

?php
    ob_start();
    session_start();
    require_once 'dbconnect.php';

    // if session is not set this will redirect to login page
    if( !isset($_SESSION['user']) ) {
        header("Location: index.php");
        exit;
    }
    // select loggedin users detail
    $res=mysql_query("SELECT * FROM users WHERE userId=".$_SESSION['user']);
    $userRow=mysql_fetch_array($res);
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome - <?php echo $userRow['userEmail']; ?></title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css" type="text/css"  />
<link rel="stylesheet" href="style.css" type="text/css" />

    <script src="assets/js/bowser.min.js"></script>
<script>
//function logout(secUrl, redirUrl)
//bowser = require('bowser');
function logout(secUrl, redirUrl) {
alert(redirUrl);
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", secUrl, true);
        xmlhttp.setRequestHeader("Authorization", "Basic logout");
        xmlhttp.send();
    } else {
        alert("Logging out automatically is unsupported for " + bowser.name
            + "\nYou must close the browser to log out.");
    }
    window.location.assign(redirUrl);
    /*setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);*/
}


function f1()
    {
       alert("f1 called");
       //form validation that recalls the page showing with supplied inputs.    
    }
</script>
</head>
<body>

    <nav class="navbar navbar-default navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="http://www.codingcage.com">Coding Cage</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="http://www.codingcage.com/2015/01/user-registration-and-login-script-using-php-mysql.html">Back to Article</a></li>
            <li><a href="http://www.codingcage.com/search/label/jQuery">jQuery</a></li>
            <li><a href="http://www.codingcage.com/search/label/PHP">PHP</a></li>
          </ul>
          <ul class="nav navbar-nav navbar-right">

            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
              <span class="glyphicon glyphicon-user"></span>&nbsp;Hi' <?php echo $userRow['userEmail']; ?>&nbsp;<span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li><a href="logout.php?logout"><span class="glyphicon glyphicon-log-out"></span>&nbsp;Sign Out</a></li>
              </ul>
            </li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav> 

    <div id="wrapper">

    <div class="container">

        <div class="page-header">
        <h3>Coding Cage - Programming Blog</h3>
        </div>

        <div class="row">
        <div class="col-lg-12" id="div_logout">
        <h1 onclick="logout(window.location.href, 'www.espncricinfo.com')">MichaelA1S1! Click here to see log out functionality upon click inside div</h1>
        </div>
        </div>

    </div>

    </div>

    <script src="assets/jquery-1.11.3-jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>


</body>
</html>
<?php ob_end_flush(); ?>

그러나 그것은 단지 새로운 위치로 당신을 리디렉션합니다. 로그 아웃이 없습니다.

유형 chrome://restart 백그라운드에서 실행되는 모든 앱이 다시 시작되면 주소 표시 줄과 크롬에서 다시 시작되며 인증 암호 캐시가 정리됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top