You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel房产代理平台:限制同一用户账号同时登录次数需求

Hey there! Let's tackle this concurrent login restriction problem for your Laravel real estate platform. I've dealt with similar SaaS account-sharing scenarios before, so here's a practical, tailored solution to stop personal account misuse:

Core Approach

The goal is to track active sessions per user, enforce a session limit based on their account type, and either block new logins or invalidate old sessions when the limit is hit. We'll leverage Laravel's session system and a database table (or cache) to keep tabs on active sessions.

Step-by-Step Implementation

1. Set Up Session Tracking (Database Option)

First, create a table to link users to their active sessions. Run this Artisan command:

php artisan make:migration create_user_sessions_table

Update the migration file with this schema:

public function up()
{
    Schema::create('user_sessions', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->onDelete('cascade');
        $table->string('session_id')->unique();
        $table->timestamp('last_activity')->useCurrent();
        $table->timestamps();
    });
}

Run the migration:

php artisan migrate

Then create a corresponding model:

php artisan make:model UserSession

2. Modify Login Logic to Enforce Limits

Override the authenticated method in your LoginController (usually in app/Http/Controllers/Auth/LoginController.php) to handle session checks:

use App\Models\UserSession;
use Illuminate\Support\Facades\Session;
use Carbon\Carbon;

protected function authenticated(Request $request, $user)
{
    // Fetch account-specific session limits from config
    $maxSessions = config('app.concurrent_sessions.' . $user->account_type);

    // Clean up expired sessions first to avoid false counts
    UserSession::where('user_id', $user->id)
        ->where('last_activity', '<', Carbon::now()->subMinutes(config('session.lifetime')))
        ->delete();

    // Count active valid sessions
    $activeSessionCount = UserSession::where('user_id', $user->id)->count();

    if ($activeSessionCount >= $maxSessions) {
        // Option 1: Kick the oldest active session (most user-friendly)
        $oldestSession = UserSession::where('user_id', $user->id)
            ->orderBy('last_activity')
            ->first();
        
        if ($oldestSession) {
            // Destroy the old session
            Session::getHandler()->destroy($oldestSession->session_id);
            $oldestSession->delete();
        }

        // Option 2: Block new login (uncomment below if you prefer strict enforcement)
        // auth()->logout();
        // return redirect()->back()->withErrors([
        //     'email' => 'Your account has reached the maximum number of concurrent logins. Please log out from another device first.'
        // ]);
    }

    // Record the current session
    UserSession::updateOrCreate(
        ['user_id' => $user->id, 'session_id' => session()->getId()],
        ['last_activity' => Carbon::now()]
    );

    return redirect()->intended($this->redirectPath());
}

3. Configure Account-Specific Limits

Add these settings to your config/app.php file for easy adjustment:

'concurrent_sessions' => [
    'personal' => 1, // Restrict personal accounts to 1 concurrent login
    'enterprise' => 10, // Allow enterprise accounts 10 concurrent logins (adjust as needed)
],

4. Update Session Activity Timestamps

Create a middleware to keep session activity up-to-date, so we can accurately detect inactive sessions:

php artisan make:middleware UpdateSessionActivity

Edit the middleware file (app/Http/Middleware/UpdateSessionActivity.php):

use App\Models\UserSession;
use Carbon\Carbon;

public function handle(Request $request, Closure $next)
{
    if (auth()->check()) {
        UserSession::where('user_id', auth()->id())
            ->where('session_id', session()->getId())
            ->update(['last_activity' => Carbon::now()]);
    }

    return $next($request);
}

Register this middleware in app/Http/Kernel.php by adding it to the web middleware group:

protected $middlewareGroups = [
    'web' => [
        // ... existing middleware
        \App\Http\Middleware\UpdateSessionActivity::class,
    ],
];

5. Clean Up Sessions on Logout

Override the loggedOut method in your LogoutController to remove the session record when a user logs out:

use App\Models\UserSession;

protected function loggedOut(Request $request)
{
    if (auth()->check()) {
        UserSession::where('user_id', auth()->id())
            ->where('session_id', session()->getId())
            ->delete();
    }

    return redirect('/');
}
Optional Enhancements
  • User Feedback: Add a flash message to notify users when their session is kicked. For example, in your main layout:

    @if(session('session_kicked'))
        <div class="alert alert-danger">
            Your account was logged in from another device, so you've been signed out.
        </div>
    @endif
    

    Modify the session destruction logic to flash this message to the old session for a better user experience.

  • Cache-Based Tracking: If you prefer not to use a database, replace the UserSession model with Redis/cache. Store active session IDs in a sorted set (sorted by last activity) for each user, then trim the set to the max session limit when needed.

  • Admin Dashboard: Add a section to let admins view active sessions per user and manually invalidate them if misuse is reported.


内容的提问来源于stack exchange,提问作者sveti petar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:15:07