当前位置: 首页 > 后端技术 > PHP

Laravel用户多字段认证优雅方案

时间:2023-03-29 15:49:42 PHP

解决方法:登录字段不超过2个(简单方案)大于等于3个登录字段(相对复杂)登录字段不超过2个我在网上看到一个比较简单的解决方案,但它不能解决所有两个字段的验证:filter_var($request->input('login'),FILTER_VALIDATE_EMAIL)?'email':'name'过滤请求中的表单内容,实现区分用户名。缺点很明显,如果对方不是email,你就瞎了。。。这里还有一个通用的解决方案:重写LoginController中的登录方法publicfunctionlogin(Requests$request){//假设字段是emailif($this->guard()->attempt(['username'=>$request->only('email'),'password'=>$request->only('password')]))){return$this->发送登录响应($request);}//假设字段是移动的if($this->guard()->attempt(['username'=>$request->only('mobile'),'password'=>$request->only('密码')])){return$this->sendLoginResponse($request);}//假设字段是用户名if($this->guard()->attempt(['username'=>$request->only('username'),'password'=>$request->only('密码')])){return$this->sendLoginResponse($request);}return$this->sendFailedLoginResponse($request);}可见,虽然可以解决问题,但是明显有悖于Laravel优雅的风格。卖了那么多花样,跟大家分享一下我的解决方法。登录字段大于或等于三个(相对复杂)。为了方便理解,我画了一个大概的流程,只画了我认为重要的部分。首先,你需要自己实现一个Illuminate\Contracts\Auth\UserProvider实现。具体可以参考Addacustomuserprovider但是我喜欢偷懒,所以直接继承了EloquentUserProvider,重写了retrieveByCredentials方法:$query=$this->createModel()->newQuery();foreach($credentialsas$key=>$value){if(!Str::contains($key,'password')){$query->orWhere($key,$value);}}}return$query->first();}注:全文的重点在于$query->where($key,$value);框架自带的,也就是说字段是和关系的;然后更改$query->where($key,$value);到$query->orWhere($key,$value);就是这样!接下来,您需要注册一个自定义的UserProvider:classAuthServiceProviderextendsServiceProvider{/***注册任何应用程序身份验证/授权服务。**@returnvoid*/publicfunctionboot(){$this->registerPolicies();Auth::provider('custom',function($app,array$config){//返回Illuminate\Contracts\Auth\UserProviderExample...returnnewCustomUserProvider(newBcryptHasher(),config('auth.providers.custom。模型'));});}}最后,我们修改auth.php的配置就大功告成了:'providers'=>['users'=>['driver'=>'eloquent','model'=>App\Models\User::class,],'custom'=>['driver'=>'custom','model'=>App\Models\User::class,]],修改web数组的provider为之前注册的自定义'guards'=>['web'=>['driver'=>'session','provider'=>'custom',],'api'=>['driver'=>'passport','provider'=>'users',],],最后看LoginController的代码:publicfunctionlogin(LoginRequest$request){$username=$request->get('username');$重新sult=$this->guard()->attempt(['username'=>$username,'email'=>$username,'mobile'=>$username,'password'=>$request->get('密码')]);如果($result){返回$this->sendLoginResponse($request);}$this->incrementLoginAttempts($request);return$this->sendFailedLoginResponse($request);}现在即使你在多个领域都做得很好......??