it-swarm.com.de

Bis zu 5 gleichzeitige Anmeldesitzungen zulassen

Ich habe Probleme beim Implementieren einer gleichzeitigen Anmeldeprüfung.

Die Site muss gleichzeitig mehr als 5 gleichzeitige Sitzungen für einen bestimmten Benutzer verhindern.

Beispiel: Benutzer Matt kann 5 aktive Sitzungen haben.

Wenn Benutzer Matt versucht, sich mit einer 6. Sitzung anzumelden, wird die Sitzung entfernt, die sich zuerst angemeldet hat und deren Aktivität nicht älter als 4 Stunden ist. Wenn alle 5 Sitzungen in den letzten 4 Stunden aktiv waren, schlägt die Anmeldung fehl und dem Benutzer wird eine Fehlermeldung/Meldung angezeigt, um den Site-Administrator zu kontaktieren.

Ich weiß, dass Wordpress WP_Session_Tokens hat, aber es scheint, dass sie nur 'Ablauf' und 'Login' ohne 'letzte_Aktivität' speichern. Gibt es eine Möglichkeit, über Wordpress oder PHP Sessions nach der letzten Aktivität zu suchen?

Wenn nicht, ist eine zweite Frage von mir, wie man das letzte Login am besten mit der aktuellen Zeit vergleicht und prüft, ob es länger als 4 Stunden dauert.

Hier ist mein aktueller Code:

// On login, check if there are already 5 sessions active for the user
function check_sessions($login) {

    global $user_ID;
    $user = get_user_by( 'slug', $login );

    //If there are less than 5 sessions, let user login normally
     if( count( wp_get_all_sessions() ) < 5 ) {
         return true;
     }

    $sessions = WP_Session_Tokens::get_instance(  $user->id );

    $all_sessions = $sessions->get_all();

    $first_login = $all_sessions[0]['login'];

    if( $first_login->diff(time()) > 4hrs ) {
        // log out first_login user & login new user
        WP_Session_Tokens::destroy( $all_sessions[0] );
        return true;
    }

    else {

       // display message to user
    }
}
add_action('wp_login','check_sessions');
5
Gil

Diese Frage hat mich sehr interessiert. Hat ungefähr 5 Stunden meines Samstags gedauert, um die vollständige Lösung zu erstellen :)

Plugin Limit Login Sessions

Es gibt noch keine Einstellungsseite, daher sind derzeit alle Optionen fest programmiert. Das Plugin implementiert folgendes (laut OP):

  1. Ein Benutzer kann maximal 5 Anmeldesitzungen in verschiedenen Browsern und Geräten durchführen.
  2. Wenn mehr als 5 Sitzungen versucht werden, wird ein Fehler angezeigt, es sei denn, die älteste Aktivitätssitzung ist älter als 4 Stunden.
  3. Wenn die älteste Aktivitätssitzung älter als 4 Stunden ist, wird diese Sitzung geschlossen und der aktuelle Anmeldeversuch wird zugelassen.

Ich habe versucht, dem Code Erklärungen mit Kommentaren hinzuzufügen. Der größte Teil des Plugin-Codes sollte selbsterklärend sein. Wenn ein Teil davon nicht klar ist, können Sie ihn gerne kommentieren.

Das GitHub-Repository finden Sie hier . Fühlen Sie sich frei, es zu teilen und zu verbessern :) Wenn jemand der Meinung ist, dass es eine nützliche Ergänzung zum WordPress-Plugin-Repository ist, lassen Sie es mich wissen und ich werde es bei Bedarf auf WordPress.org hochladen.

<?php
/*
Plugin Name: Limit Login Sessions
Version: 1.0.0
Author: Sisir Kanti Adhikari
Author URI: https://sisir.me/
Description: Limits users login sessions.
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Limit Login Sessions is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.

Limit Login Sessions is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (http://www.gnu.org/licenses/gpl-2.0.html)
 for more details.

*/

add_filter('authenticate', 'lls_authenticate', 1000, 2);

function lls_authenticate($user, $username){

    if(!username_exists($username) || !$user = get_user_by('login', $username))
        return null; // will trigger WP default no username/password matched error

    // setup vars
    $max_sessions = 5;
    $max_oldest_allowed_session_hours = 4;
    $error_code = 'max_session_reached';
    $error_message = "Maximum $max_sessions login sessions are allowed. Please contact site administrator.";

    // 1. Get all active session for this user
    $manager = WP_Session_Tokens::get_instance( $user->ID );
    $sessions =  $manager->get_all();

    // 2. Count all active session
    $session_count = count($sessions);

    // 3. Return okay if active session less then $max_sessions
    if($session_count < $max_sessions)
        return $user;

    $oldest_activity_session = lls_get_oldest_activity_session($sessions);

    // 4. If active sessions is equal to 5 then check if a session has no activity last 4 hours
    // 5. if oldest session have activity return error
    if(
        ( $session_count >= $max_sessions && !$oldest_activity_session ) // if no oldest is found do not allow
        || ( $session_count >= $max_sessions && $oldest_activity_session['last_activity'] + $max_oldest_allowed_session_hours * HOUR_IN_SECONDS > time())
    ){
        return new WP_Error($error_code, $error_message);
    }

    // 5. Oldest activity session doesn't have activity is given recent hours
    // destroy oldest active session and authenticate the user

    $verifier = lls_get_verifier_by_session($oldest_activity_session, $user->ID);

    lls_destroy_session($verifier, $user->ID);

    return $user;

}

function lls_destroy_session($verifier, $user_id){

    $sessions = get_user_meta( $user_id, 'session_tokens', true );

    if(!isset($sessions[$verifier]))
        return true;

    unset($sessions[$verifier]);

    if(!empty($sessions)){
        update_user_meta( $user_id, 'session_tokens', $sessions );
        return true;
    }

    delete_user_meta( $user_id, 'session_tokens');
    return true;

}

function lls_get_verifier_by_session($session, $user_id = null){

    if(!$user_id)
        $user_id = get_current_user_id();

    $session_string = implode(',', $session);
    $sessions = get_user_meta( $user_id, 'session_tokens', true );

    if(empty($sessions))
        return false;

    foreach($sessions as $verifier => $sess){
        $sess_string = implode(',', $sess);

        if($session_string == $sess_string)
            return $verifier;

    }

    return false;
}


function lls_get_oldest_activity_session($sessions){
    $sess = false;

    foreach($sessions as $session){

        if(!isset($session['last_activity']))
            continue;

        if(!$sess){
            $sess = $session;
            continue;
        }

        if($sess['last_activity'] > $session['last_activity'])
            $sess = $session;

    }

    return $sess;
}

// add a new key to session token array

add_filter('attach_session_information', 'lls_attach_session_information');

function lls_attach_session_information($session){
    $session['last_activity'] = time();
    return $session;
}

add_action('template_redirect', 'lls_update_session_last_activity');

function lls_update_session_last_activity(){

    if(!is_user_logged_in())
        return;

    // get the login cookie from browser
    $logged_in_cookie = $_COOKIE[LOGGED_IN_COOKIE];

    // check for valid auth cookie
    if( !$cookie_element = wp_parse_auth_cookie($logged_in_cookie) )
        return;

    // get the current session
    $manager = WP_Session_Tokens::get_instance( get_current_user_id() );

    $current_session = $manager->get($cookie_element['token']);

    if(
        $current_session['expiration'] <= time() // only update if session is not expired
        || ( $current_session['last_activity'] + 5 * MINUTE_IN_SECONDS ) > time() // only update in every 5 min to reduce db load
    ){
        return;
    }

    $current_session['last_activity'] = time();
    $manager->update($cookie_element['token'], $current_session);

}

Für einige Funktionen musste ich direkt mit dem Datenbankwert user_meta interagieren. Die Klasse hatte einige Methoden geschützt, so dass nicht direkt zugegriffen werden konnte.

Das Plugin wird lokal mit WP v4.3.1 getestet.

12
Sisir

Es ist unmöglich, eine Antwort auf die gestellte Frage zu haben, da das http-Protokoll keine Langzeitsitzungen hat. Eine Sitzung auf http ist eine Anforderung und eine Antwort.

Sitzungen, wie wir sie im Internet kennen, sind lediglich Hacks, mit denen die Notwendigkeit beseitigt werden soll, bei jedem Seitenaufruf Login- und Pass-Informationen bereitzustellen.

wordpress 4.1 hat einen kleinen Schritt getan, um eine "Sitzung" besser mit einem Endgerät zu verknüpfen, aber es ist nur ein besserer Hack als zuvor und es ist nicht 100% zuverlässig, da Sie die Cookies immer noch kopieren und/oder Proxy verwenden können, um sie zu faulen zu glauben, dass zwei separate Endgeräte zu derselben Sitzung gehören. OTOH wird es denken, dass zwei Browser auf dem gleichen Computer auf verschiedenen Geräten sind.

Sie versuchen nur, DRM zum Laufen zu bringen, und in den letzten 20 Jahren wurde eines bei DRM bewiesen: 1. Es verhindert nicht, dass Menschen "illegalen" Zugriff auf Inhalte erhalten, es dauert nur ein bisschen länger. 2. Es nervt die zahlenden Kunden.

Ihr spezifisches Schema hängt davon ab, ob Sie wissen, welches Gerät als nächstes verwendet wird, und ob Sie davon ausgehen, dass es das zuletzt aktive Gerät ist, hat keinen Sinn. Die aktive OTOH 5-Sitzung wird wahrscheinlich für meinen gesamten Block ausreichen, sodass Sie nicht einmal "Content-Diebstahl blockieren"

Es ist nicht so, dass die Frage überhaupt keinen Wert hat. Ich kann so etwas sehen, um die Sicherheit zu verbessern, aber DRM hängt sehr stark von den kleinen Details ab. Wenn Sie einen modischen, aber kritischen Begriff wie "aktive Sitzungen" verwenden, ohne die Details zuerst zu definieren, bedeutet dies für mich, dass Sie dies nicht tun Sie müssen wirklich wissen, was Sie tatsächlich vom System erwarten, da das Herausfinden der "aktiven Sitzungen" der kritischste Teil bei der Implementierung Ihres Schemas ist.

0
Mark Kaplun