【问题标题】:Laravel - Custom authentification queryLaravel - 自定义身份验证查询
【发布时间】:2018-07-11 13:22:28
【问题描述】:

如何将DESC 添加到默认登录sql 查询?

我的意思是默认类似于

select * from users where name = user_name limit 1

如何添加

select * from users where name = user_name ORDER BY id DESC limit 1?

我知道名称列应该只包含唯一值,我的登录系统不同(另一个表中的一些预定义用户)并且我需要多个具有相同名称的用户注册。我只想登录数据库中的最后一条记录。请帮助我如何在 laravel 中自定义模型提供程序?我不知道要修改哪些文件才能使其正常工作。

这是我的 LoginController.php 但你可以忽略它(我添加它是因为一些用户需要它)只需查看来自 php artisan make:auth 的默认 loginController

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Session;
class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
/**
     * Check either username or email.
     * @return string
     */

public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

      public function username()
    {
        $identity  = Session::get('table_id');
        $fieldName = 'name';
        request()->merge([$fieldName => $identity]);

        return $fieldName;
    }

    /**
     * Validate the user login.
     * @param Request $request
     */
    protected function validateLogin(Request $request)
    {
        $this->validate(
            $request,
            [
                'password' => 'required|string',
            ],
            [
                'password.required' => 'Password is required',
            ]
        );
    }
    /**
     * @param Request $request
     * @throws ValidationException
     */
    protected function sendFailedLoginResponse(Request $request)
    {
        $request->session()->put('login_error', trans('auth.failed'));
        throw ValidationException::withMessages(
            [
                'error' => [trans('auth.failed')],
            ]
        );
    }

     protected function attemptLogin(Request $request)
    {
        $remember = true;
        return $this->guard()->attempt(         
            $this->credentials($request), $remember
        );
    }
}

我的 LoginController 中的所有方法都覆盖了来自 vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php 的方法

【问题讨论】:

  • 显示您的查询
  • 什么意思?我发布了需要在laravel默认登录查询中添加order by id DESC的查询
  • 这是最终的sql查询。你是怎么得到的??

标签: php sql laravel laravel-5.6 laravel-authentication


【解决方案1】:

将 LoginController 替换为以下内容。我已经删除了 username() 方法并替换了 attemptLogin() 方法来获取数据库中的最后一个用户,因为你的会话值为 'table_id'。

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Session;
use App\User;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->middleware('guest')->except('logout');
        $this->user = $user;
    }
/**
     * Check either username or email.
     * @return string
     */

public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Validate the user login.
     * @param Request $request
     */
    protected function validateLogin(Request $request)
    {
        $this->validate(
            $request,
            [
                'password' => 'required|string',
            ],
            [
                'password.required' => 'Password is required',
            ]
        );
    }
    /**
     * @param Request $request
     * @throws ValidationException
     */
    protected function sendFailedLoginResponse(Request $request)
    {
        $request->session()->put('login_error', trans('auth.failed'));
        throw ValidationException::withMessages(
            [
                'error' => [trans('auth.failed')],
            ]
        );
    }

protected function attemptLogin(Request $request, User $user)
{
    if (session()->has('table_id') != true) return redirect()->back()->withErrors(['error' => 'No username is set.']);
    $userName = $user->where('name', session('table_id'))->orderBy('id', 'desc')->first()->name;
    $remember = true;
    if (Auth::attempt(['name' => $userName, 'password' => request('password')], $remember)) {
        return redirect()->intended();
    }
}

}

【讨论】:

  • 你能提供一个使用该方法的例子吗?这是我的 LoginController 构造函数:public function __construct() { $this-&gt;middleware('guest')-&gt;except('logout'); },登录方法是默认的 public function login(Request $request) {
  • 你使用的是默认的 laravel auth 登录页面吗?你到底想做什么?让用户输入电子邮件和密码,并让它登录数据库中与该电子邮件和密码匹配的最后一个用户?
  • 是的,我使用的是默认的 laravel auth 登录页面,但我修改了控制器,以便我可以从应用程序中较早的会话设置中提供用户名。我从会话中提供用户名,用户只输入密码,如果密码与用户名匹配,则用户登录。我只需要在特定用户的最新记录上进行登录。我只需要在登录中添加那个 ORDER BY 子句,其余的就行了。
  • 你能添加你的控制器方法来处理当前的登录吗?
  • 我在主要问题中添加了它。我的 LoginController 中的所有方法都覆盖了来自 vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php 的方法
【解决方案2】:

您不应更改/删除任何框架文件和代码。 在您的登录控制器顶部添加此特征:

use AuthenticatesUsers;

然后您可以覆盖所有登录功能。

为了验证用户名/密码,只需覆盖 attemptLogin() 函数。

【讨论】:

  • 我这样做了,但我不知道在 attemptLogin() 方法中添加-&gt;orderBy('id', 'desc') 的位置。你能帮忙吗?这是我的方法:protected function attemptLogin(Request $request) { $remember = true; return $this-&gt;guard()-&gt;attempt( $this-&gt;credentials($request), $remember ); }
  • 您不需要“desc”,因为如果您的查询找到匹配项,您将拥有一条记录,就像提到的其他答案一样,您应该使用-&gt;first()
  • 我真的要最新,默认登录是匹配第一条记录的密码。
【解决方案3】:

因此,如果我正确理解您的问题,您希望在身份验证时更改默认 sql 查询以选择用户。 在attemptLogin 方法中,您调用attempt,它位于StatefulGuard 接口中,实现在/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php 中,因此您需要覆盖完整的attempt 方法,或者其中的方法。

【讨论】:

  • attemptLogin 这是来自vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php 的默认方法我只将真实值添加到记住令牌中,因此用户登录时会自动选中“记住我”。让我们换一种说法,假设我在 LoginController 中什么都没有(我有,但它是默认的,没有任何修改)。如何在登录查询中添加 ORDER BY desc?即使它在默认的 LoginController 中没有用,因为每个名称都是唯一的,我该如何添加它?
  • 想象一个全新的php artisan make:auth 登录系统。我想在登录查询中按 DESC 添加 ORDER。如果你有可能制作一个新的 laravel 应用程序 (laravel new blog) 然后php artisan make:auth
【解决方案4】:

我找到了另一种可行的解决方案,但我相信它会搞砸(我不确定)这就是为什么我将 Polaris 的答案选为正确的答案。

您可以保留默认的 LoginController 并像这样修改 App/User.php: 它基本上覆盖了 Illuminate\Auth\EloquentUserProvider; 中使用的 retrieveByCredentials 方法。问题是我相信这个方法通常不会直接从Users.php 访问,所以你不会直接覆盖它。但由于某种原因它有效:))。

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Auth\EloquentUserProvider;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

        public function retrieveByCredentials(array $credentials)
    {
        if (empty($credentials) ||
           (count($credentials) === 1 &&
            array_key_exists('password', $credentials))) {
            return;
        }

        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value) {
            if (Str::contains($key, 'password')) {
                continue;
            }

            if (is_array($value) || $value instanceof Arrayable) {
                $query->whereIn($key, $value);
            } else {
                $query->where($key, $value);
            }
        }

       return $query->orderBy('id', 'desc')->first();
    }
}

【讨论】:

    猜你喜欢
    • 2015-02-23
    • 2014-03-30
    • 2016-04-18
    • 1970-01-01
    • 2017-07-27
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多