كيفية تسجيل الخروج من المستخدم من موقع الويب باستخدام المصادقة الأساسية؟

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

سؤال

هل من الممكن تسجيل الخروج من المستخدم من موقع ويب إذا كان يستخدم المصادقة الأساسية؟

جلسة القتل ليست كافية ، لأنه بمجرد مصادقة المستخدم ، يحتوي كل طلب على معلومات تسجيل الدخول ، لذلك يتم تسجيل المستخدم تلقائيًا في المرة القادمة التي يقوم فيها بالوصول إلى الموقع باستخدام نفس بيانات الاعتماد.

الحل الوحيد حتى الآن هو إغلاق المتصفح ، لكن هذا غير مقبول من وجهة نظر قابلية الاستخدام.

هل كانت مفيدة؟

المحلول

لم تكن المصادقة الأساسية مصممة لإدارة التسجيل. يمكنك القيام بذلك ، ولكن ليس تلقائيًا تمامًا.

ما عليك فعله هو جعل المستخدم ينقر على رابط تسجيل الدخول ، وإرسال "401 غير مصرح به" ، وذلك باستخدام نفس المجال وفي نفس مستوى مجلد عنوان URL مثل 401 العادي الذي ترسله طلب تسجيل الدخول.

يجب توجيهها لإدخال بيانات الاعتماد الخاطئة بعد ذلك ، على سبيل المثال. كلمة مستخدم ومسمة فارغة ، واستجابة ترسل صفحة "لقد قمت بتسجيل الدخول بنجاح". ستؤدي بيانات الاعتماد الخاطئة/الفارغة إلى الكتابة فوق بيانات الاعتماد الصحيحة السابقة.

باختصار ، يقوم البرنامج النصي logout بإحكام منطق البرنامج النصي لتسجيل الدخول ، فقط إرجاع صفحة النجاح إذا كان المستخدم ليس تمرير أوراق الاعتماد الصحيحة.

والسؤال هو ما إذا كان مربع كلمة مرور كلمة مرور كلمة المرور فضوليًا إلى حد ما سوف يفي بقبول المستخدم. يمكن لمديري كلمة المرور الذين يحاولون إملاء كلمة المرور تلقائيًا أن تعترض الطريق هنا.

تحرير لإضافة رداً على التعليق: إعادة السطوع هي مشكلة مختلفة قليلاً (ما لم تكن بحاجة إلى تسجيل دخول/تسجيل دخول من خطوتين بوضوح). يجب أن ترفض (401) أول محاولة للوصول إلى رابط Relogin ، بدلاً من قبول الثانية (التي من المفترض أن لها اسم مستخدم/كلمة مرور مختلفة). هناك بعض الطرق التي يمكنك بها القيام بذلك. يمكن للمرء أن يتضمن اسم المستخدم الحالي في رابط تسجيل الدخول (على سبيل المثال /Relogin؟ اسم المستخدم) ، ويرفض عندما تتطابق بيانات الاعتماد مع اسم المستخدم.

نصائح أخرى

إضافة إلى إجابة بوبنس ...

مع AJAX ، يمكنك الحصول على رابط/زر "تسجيل الخروج" الخاص بك إلى وظيفة JavaScript. اطلب من هذه الوظيفة إرسال xmlhttprequest مع اسم مستخدم وكلمة مرور سيئة. يجب أن يعود هذا إلى 401. ثم قم بتعيين المستند. التراجع إلى صفحة ما قبل السد. وبهذه الطريقة ، لن يرى المستخدم أبدًا مربع حوار تسجيل الدخول الإضافي أثناء تسجيل الدخول ، ولا يجب أن يتذكر وضع بيانات اعتماد سيئة.

اطلب من المستخدم انقر فوق رابط إلى https: // log: out@example.com/. هذا من شأنه أن يكتب بيانات الاعتماد الحالية مع تلك غير صالحة ؛ تسجيلها.

يمكنك القيام بذلك بالكامل في جافا سكريبت:

IE لديه (لفترة طويلة) واجهة برمجة تطبيقات قياسية لمسح ذاكرة التخزين المؤقت المصادقة الأساسية:

document.execCommand("ClearAuthenticationCache")

يجب أن تعود بشكل صحيح عندما يعمل. يعيد إما كاذبة أو غير محددة أو تهب على متصفحات أخرى.

المتصفحات الجديدة (اعتبارًا من ديسمبر 2012: Chrome ، Firefox ، Safari) لها سلوك "سحري". إذا رأوا أ ناجح طلب المصادقة الأساسية مع أي اسم مستخدم آخر زائف (دعنا نقول logout) يقومون بمسح ذاكرة التخزين المؤقت لبيانات الاعتماد وربما تعيينها لاسم مستخدم BOGUS الجديد ، والذي تحتاج إلى التأكد من أنه ليس اسم مستخدم صالح لعرض المحتوى.

المثال الأساسي على ذلك هو:

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

طريقة "غير متزامنة" للقيام بما سبق هي إجراء مكالمة Ajax باستخدام 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.
بوسر يستخدم للكشف عن المتصفح ، ويستخدم jQuery أيضًا.

- Securl هو عنوان URL إلى منطقة محمية كلمة المرور التي يمكن من خلالها تسجيل الخروج.
- Redirurl هو عنوان URL لمنطقة محمية غير كلمة مرور (صفحة نجاح تسجيل الدخول).
- قد ترغب في زيادة مؤقت إعادة التوجيه (حاليًا 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);
}

هذا غير ممكن مباشرة مع المصادقة الأساسية.

لا توجد آلية في مواصفات HTTP للخادم لإخبار المتصفح بالتوقف عن إرسال بيانات الاعتماد التي قدمها المستخدم بالفعل.

هناك "اختراقات" (انظر الإجابات الأخرى) التي تتضمن عادة استخدام XMLHTTPrequest لإرسال طلب HTTP مع بيانات اعتماد غير صحيحة للكتابة فوق تلك المقدمة في الأصل.

إليك مثال JavaScript بسيط جدًا باستخدام jQuery:

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

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

هذا السجل من مستخدم السجل دون أن يعرض له مربع تسجيل الدخول للمتصفح مرة أخرى ، ثم إعادة توجيهه إلى أ تسجيل الخروج صفحة

انها في الواقع بسيطة جدا.

ما عليك سوى زيارة ما يلي في متصفحك واستخدم بيانات الاعتماد الخاطئة: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 إلى نهاية تسجيل الدخول الخاصة بك. يجب أن تقبل نهاية تسجيل الدخول الخاصة بك مستخدم LogOut. بمجرد قبول النهاية الخلفية ، مسح المستعرض المستخدم الحالي ويفترض المستخدم "تسجيل الخروج".

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

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

2) الآن عندما يعود المستخدم إلى ملف الفهرس العادي ، فسوف يحاول إدخال النظام التلقائي في النظام مع "تسجيل الخروج" للمستخدم ، في هذه المرة الثانية ، يجب عليك حظره بالرد مع 401 لاستدعاء مربع الحوار تسجيل الدخول/كلمة المرور.

3) هناك العديد من الطرق للقيام بذلك ، لقد قمت بإنشاء نهايتين لتسجيل الدخول ، واحدة تقبل مستخدم تسجيل الدخول والطريقة التي لا. تستخدم صفحة تسجيل الدخول العادية الخاصة بي تلك التي لا تقبل ، تستخدم صفحة تسجيل الدخول الخاصة بي تلك التي تقبلها.

  • استخدم معرف الجلسة (ملف تعريف الارتباط)
  • إبطال معرف الجلسة على الخادم
  • لا تقبل المستخدمين بمعرفات جلسة غير صالحة

قمت بتحديث حل 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 في شريط العناوين والكروم ، مع جميع تطبيقاته التي تعمل في الخلفية ، سيتم إعادة تشغيلها وسيتم تنظيف ذاكرة التخزين المؤقت لكلمة مرور Auth.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top