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

Laravel 8 如何验证用户登录时的子地点访问权限

Laravel 8 基于子地点的登录验证实现

方案一:自定义验证规则

1. 创建自定义验证规则

执行Artisan命令生成规则文件:

php artisan make:rule ValidSubLocation

2. 编写验证逻辑

打开app/Rules/ValidSubLocation.php,修改passes方法实现子地点权限验证:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\DB;

class ValidSubLocation implements Rule
{
    protected $userId;

    public function __construct($userId)
    {
        $this->userId = $userId;
    }

    public function passes($attribute, $value)
    {
        // 校验用户对应的子地点是否存在且处于启用状态
        return DB::table('user_locations')
            ->where('user_id', $this->userId)
            ->where('sub_location_id', $value)
            ->where('status', 'Y')
            ->exists();
    }

    public function message()
    {
        return '您无权访问该子地点,或该子地点已被禁用。';
    }
}

3. 在登录请求中绑定规则

创建登录请求类:

php artisan make:request LoginRequest

打开app/Http/Requests/LoginRequest.php,配置验证规则和错误提示:

<?php

namespace App\Http\Requests;

use App\Rules\ValidSubLocation;
use Illuminate\Foundation\Http\FormRequest;

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'user_id' => 'required|exists:users,user_id,status,Y',
            'password' => 'required',
            'sub_location_id' => ['required', new ValidSubLocation($this->user_id)],
        ];
    }

    public function messages()
    {
        return [
            'user_id.exists' => '该用户不存在或已被禁用',
            'password.required' => '请输入密码',
            'sub_location_id.required' => '请选择子地点',
        ];
    }
}

4. 控制器处理登录逻辑

修改LoginController的login方法,使用自定义请求完成验证:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    public function login(LoginRequest $request)
    {
        // 验证用户密码
        if (!Auth::attempt(['user_id' => $request->user_id, 'password' => $request->password])) {
            return back()->withErrors([
                'password' => '密码错误',
            ])->withInput();
        }

        // 将子地点ID存入session,方便后续业务权限控制
        session(['sub_location_id' => $request->sub_location_id]);

        return redirect()->intended('/dashboard');
    }
}

方案二:直接在控制器内完成所有验证

如果不需要复用验证规则,可直接在控制器中整合所有校验逻辑:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        // 基础字段验证
        $request->validate([
            'user_id' => 'required|exists:users,user_id,status,Y',
            'password' => 'required',
            'sub_location_id' => 'required',
        ], [
            'user_id.exists' => '该用户不存在或已被禁用',
            'password.required' => '请输入密码',
            'sub_location_id.required' => '请选择子地点',
        ]);

        // 校验子地点权限
        $hasValidSubLocation = DB::table('user_locations')
            ->where('user_id', $request->user_id)
            ->where('sub_location_id', $request->sub_location_id)
            ->where('status', 'Y')
            ->exists();

        if (!$hasValidSubLocation) {
            return back()->withErrors([
                'sub_location_id' => '您无权访问该子地点,或该子地点已被禁用。',
            ])->withInput();
        }

        // 验证密码正确性
        if (!Auth::attempt(['user_id' => $request->user_id, 'password' => $request->password])) {
            return back()->withErrors([
                'password' => '密码错误',
            ])->withInput();
        }

        // 存储子地点信息到session
        session(['sub_location_id' => $request->sub_location_id]);

        return redirect()->intended('/dashboard');
    }
}

额外优化建议

  • 给User模型和UserLocation模型建立关联,方便后续业务调用:
    在app/Models/User.php中添加:
    public function userLocations()
    {
        return $this->hasMany(UserLocation::class, 'user_id');
    }
    
  • 登录成功后存入session的sub_location_id,可在后续中间件中校验,确保用户所有请求都限定在该子地点范围内。

内容的提问来源于stack exchange,提问作者Lokesh M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:15:44