Вход только в том случае, если пользователь активен, используя Laravel
В настоящее время я работаю над своим приложением Laravel и предотвращаю спам. Я решил, что только активные пользователи могут войти в систему.
В настоящее время я использую систему входа в систему Laravel, как в официальном учебнике официального сайта Laravel, здесь мое действие формы:
<form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/login') }}">
Это работает отлично, однако я бы хотел проверить, активен ли пользователь, если он неактивен, он будет перенаправлен на страницу активации, иначе он войдет в систему.
Есть ли простой способ сделать это, или я обязан создать новый контроллер, маршруты и другие проверки? Спасибо.
Изменить: забыл упомянуть, что у меня есть "активный" столбец в моей базе данных.
Ответы
Ответ 1
Laravel 5.4/5.5
Отмените функцию по умолчанию login()
, поместив эту функцию в LoginController
:
public function login(\Illuminate\Http\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);
}
// This section is the only change
if ($this->guard()->validate($this->credentials($request))) {
$user = $this->guard()->getLastAttempted();
// Make sure the user is active
if ($user->active && $this->attemptLogin($request)) {
// Send the normal successful login response
return $this->sendLoginResponse($request);
} else {
// Increment the failed login attempts and redirect back to the
// login form with an error message.
$this->incrementLoginAttempts($request);
return redirect()
->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors(['active' => 'You must be active to login.']);
}
}
// 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);
}
Переопределение метода login()
таким образом рекомендуется по многим другим ответам на этот вопрос, поскольку он позволяет использовать многие из более расширенных функций проверки подлинности Laravel 5.4+, такие как регулирование входа в систему, несколько драйверов защиты аутентификации/поставщиками и т.д., все еще позволяя вам установить настраиваемое сообщение об ошибке.
Laravel 5.3
Измените или переопределите функцию postLogin()
в AuthController
, чтобы выглядеть так:
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath()) // Change this to redirect elsewhere
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'You must be active to login.'
]);
}
}
return redirect($this->loginPath())
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
Этот код перенаправляет обратно на страницу входа с сообщением об ошибке, когда пользователь неактивен. Если вы хотите перенаправить на страницу аутентификации, вы измените строку, помеченную комментарием Change this to redirect elsewhere
.
Ответ 2
В Laravel 5.4 откройте Auth/LoginController.php
и добавьте эту функцию:
/**
* Get the needed authorization credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(\Illuminate\Http\Request $request)
{
//return $request->only($this->username(), 'password');
return ['email' => $request->{$this->username()}, 'password' => $request->password, 'status' => 1];
}
И все готово..!
Ответ 3
Это решение основано на идее Can Celik и было протестировано с Laravel 5.3.
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|exists:users,' . $this->username() . ',active,1',
'password' => 'required',
]);
}
Последние два параметра, разделенные запятыми (active,1
), действуют как предложение WHERE (WHERE active = '1'
) и могут быть альтернативно записаны следующим образом:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => [
'required',
Rule::exists('users')->where(function ($query) {
$query->where('active', 1);
}),
],
'password' => 'required'
]);
}
Обычно метод проверки проверяет только заполнение полей электронной почты и пароля. С изменением выше мы требуем, чтобы данный адрес электронной почты был найден в строке DB с значением active
, установленным в 1.
ОБНОВЛЕНИЕ (проверено с помощью Laravel 5.5):
Вы также можете настроить сообщение:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|exists:users,' . $this->username() . ',active,1',
'password' => 'required',
], [
$this->username() . '.exists' => 'The selected email is invalid or the account has been disabled.'
]);
}
Обратите внимание, что указанное выше сообщение будет отображаться как при отсутствии адреса электронной почты, так и при отключении учетной записи.
Ответ 4
в AuthController переопределяет метод getCredentials следующим образом:
protected function getCredentials(Request $request) {
$request['active'] = TRUE;
return $request->only($this->loginUsername(), 'password', 'active');
}
убедитесь, что столбец активен в пользовательской таблице...
Ответ 5
Вам не нужно переопределять всю функцию. Вы можете просто изменить Validator в AuthController, чтобы добиться того, что добавление валидации "существует: таблица, столбец".
Предположим, что у вас есть таблица пользователей с электронной почтой, паролем и активными полями.
'email' => 'exists:users,email,active,1'
Вот функция validotor должна выглядеть как в AuthController.php
protected function validator(array $data)
{
return Validator::make($data, [
'email' => 'required|email|max:255|exists:users,email,active,1',
'password' => 'required|confirmed'
]);
}
или если вы используете мягкие удаления, это тоже должно работать.
'email' => 'exists:users,email,deleted_at,NULL'
Вы также можете проверить правило проверки по этой ссылке http://laravel.com/docs/5.1/validation#rule-exists
Ответ 6
Если кто-то использует запрос ajax при входе в систему и хочет иметь настраиваемое сообщение, вот как я достиг этого в контроллере входа в систему:
функция login()
// This section is the only change
if ($this->guard()->validate($this->credentials($request))) {
$user = $this->guard()->getLastAttempted();
// Make sure the user is active
if ($user->status == 1 && $this->attemptLogin($request)) {
// Send the normal successful login response
return $this->sendLoginResponse($request);
} else {
// Increment the failed login attempts and redirect back to the
// login form with an error message.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request, true);
}
}
И другие функции
public function sendLoginResponse(Request $request)
{
$redirectTo = false;
if ($request->headers->get('referer') == env('APP_URL') . '/' || $request->headers->get('referer') == env('APP_URL') . '/login') {
$redirectTo = $this->redirectPath();
}
if ($request->expectsJson()) {
return response()->json(['status' => true, 'user' => auth()->user(), 'redirectTo' => $redirectTo, 'fragments' => [
'#main-nav' => view('includes.nav')->render()
]]);
} else {
return redirect($redirectTo);
}
}
public function sendFailedLoginResponse(Request $request, $user_not_active = fasle)
{
if ($user_not_active) {
return response()->json(['status' => false, 'email' => 'Your account is not active.']);
}
return response()->json(['status' => false, 'email' => 'Incorrect login credentials.']);
}
Ответ 7
В случае, если кто-то пришел сюда, ища информацию о Laravel 5.4/5.5, и это позволяет использовать настраиваемое сообщение только для этого сценария (а не комбинированное сообщение), здесь для ответа от https://laracasts.com/discuss/channels/laravel/user-account-status
Переопределить метод "authenticated" в файле your'app/Http/Controllers/Auth/LoginController.php`:
/**
* The user has been authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $user
* @return mixed
*/
protected function authenticated(Request $request, $user)
{
if ($user->status_id == 2) { // or whatever status column name and value indicates a blocked user
$message = 'Some message about status';
// Log the user out.
$this->logout($request);
// Return them to the log in form.
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([
// This is where we are providing the error message.
$this->username() => $message,
]);
}
}
Ответ 8
Я проверяю, что пользователь активируется путем перезаписи функции sendLoginResponse в LoginController
protected function sendLoginResponse(Request $request)
{
if($this->guard()->user()->active == 0){
$this->guard()->logout();
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors(['active' => 'User in not activated.']);
}
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
Ответ 9
Спасибо @Can_Celik
таким образом я смог решить свою проблему, потому что я использовал json response
с jquery.
/**
* Validate the user login request.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email|exists:users_table,email,account_status_colunm,active_value',
'password' => 'required',
]);
}
затем в файле validation.php
добавьте это в свои строки пользовательской проверки
...
'email' => [
'exists' => 'Account has been disabled. Contact our team.'
],
это обо всем... отлично работает ...
Ответ 10
Я новичок в Laravel, и это тоже нацелено на новичков. Давние работники не стесняются говорить мне, почему это плохая практика, так как я искренне не знаю ничего лучшего.
По состоянию на 24 августа 2019 года - с использованием Laravel 5.8 - это моя личная реализация.
Сделанные предположения:
-
Вы начали использовать Artisan Make: Auth
-
Вы добавили "active" как bool (tinyInt) в свою таблицу User и обновили соответствующие модели и т. Д...
-
Вы пытаетесь запретить пользователям получать доступ к вашему приложению через стандартную аутентификацию, когда: 'active' = 0.
Если это так, вы можете оставить свой LoginController в покое.
Вместо этого откройте "Illuminate/Auth/Middleware/Authenticate.php" и замените метод handle() следующим:
public function handle($request, Closure $next, ...$guards)
{
if(!$request->user()->active){
// either abort with simple 403 access denied page
// abort(403, "You don't have permissions to access this area");
// OR force Logout and redirect back to the login page
return redirect('login')->with($this->auth->logout());
}
$this->authenticate($request, $guards);
return $next($request);
}
Примечание: Auth :: logout() здесь не будет работать, но он уже загружен через конструктор в верхней части файла.
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
Так что вы можете просто использовать $this-> auth-> logout(); вместо.
Подумайте об этом - вы можете очень легко поменять 'Active' практически на любой критерий и обновить это промежуточное ПО точно так же! Надеюсь это поможет!
Ответ 11
Вы можете использовать Eloquent. https://laravel.com/docs/5.5/eloquent#query-scopes
как это:
class User extends Authenticatable {
...
/**
* The "booting" method of the model.
*
* @return void
*/
protected static function boot() {
parent::boot();
static::addGlobalScope('scopeActive', function (Builder $builder) {
$builder->where('active', 1);
});
}
...