Я разрабатываю приложение Laravel. Мое приложение использует встроенную функцию аутентификации Laravel. В аутентификации Laravel при регистрации пользователя отправляется письмо с подтверждением. Когда пользователь проверяет адрес электронной почты, щелкнув ссылку внутри сообщения электронной почты, пользователь должен снова войти в систему, чтобы подтвердить адрес электронной почты, если пользователь еще не вошел в систему.
VerificationController
class VerificationController extends Controller
{
use VerifiesEmails, RedirectsUsersBasedOnRoles;
/**
* Create a new controller instance.
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
public function redirectPath()
{
return $this->getRedirectTo(Auth::guard()->user());
}
}
Я пробовал комментировать эту строчку.
$this->middleware('auth');
Но это не работает, а вместо этого выдает ошибку. Как я могу включить Laravel, чтобы иметь возможность проверять электронную почту, даже если пользователь не вошел в систему?
Что делает RedirectsUsersBasedOnRoles? Когда вы говорите «Это не работает», что вы имеете в виду; вы получаете ошибку? Что за ошибка?
Он выдает ошибку, потому что ожидает экземпляр вашего пользователя. См .: github.com/laravel/framework/blob/…
Спасибо, Адам. Спасибо, Лук, что указал на разумную причину. Ваше здоровье
как так @Loek? URL подписан.






Сначала удалите строку $this->middleware('auth');, как вы это сделали.
Затем скопируйте метод verify из свойства VerifiesEmails на свой VerificationController и немного измените его. Метод должен выглядеть так:
public function verify(Request $request)
{
$user = User::find($request->route('id'));
if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
throw new AuthorizationException;
}
if ($user->markEmailAsVerified())
event(new Verified($user));
return redirect($this->redirectPath())->with('verified', true);
}
Это отменяет метод в трейте VerifiesUsers и удаляет проверку авторизации.
Безопасность (поправьте меня, если я ошибаюсь!)
Это по-прежнему безопасно, так как запрос подписан и проверен. Кто-то может проверить адрес электронной почты другого пользователя, если он каким-то образом получит доступ к проверочному электронному письму, но в 99% случаев это вряд ли вообще представляет собой риск.
Могу ли я использовать этот метод, не беспокоясь о проблемах безопасности?
Это было отредактировано для Laravel 6? В предыдущих версиях ваше индивидуальное сравнение хешей не было обязательным, верно?
Вызов неопределенного метода App \ User :: getEmailForVerification ()
@SeadLab убедитесь, что вы включили трейт MustVerifyEmail в модель User. Кроме этого, я не уверен, изменилось ли что-нибудь в Laravel 7.
если вы хотите активировать учетную запись пользователя без входа в систему, вы можете сделать это за 2 шага
1- Удалить или прокомментировать промежуточное ПО Auth в VerificationController
Пример ниже:
public function __construct()
{
//$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
2- поскольку проверка маршрута проходит через {id}, вы можете просто отредактировать функцию проверки, чтобы найти пользователя по запросу идентификатора маршрута, как показано ниже:
путь к файлу: *: \ yourproject \ vendor \ laravel \ framework \ src \ Illuminate \ Foundation \ Auth \ VerifyEmails.php
$user = User::findOrfail($request->route('id'));
Полный пример
public function verify(Request $request)
{
$user = User::findOrfail($request->route('id'));
if (! hash_equals((string) $request->route('id'), (string) $user->getKey())) {
throw new AuthorizationException;
}
if (! hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
throw new AuthorizationException;
}
if ($user->hasVerifiedEmail()) {
return redirect($this->redirectPath())->with('verified', true);
}
if ($user->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect($this->redirectPath())->with('registered', true);
}
Привет, серфинг. Пожалуйста, подумайте о добавлении описания к вашему примеру кода.
// For Laravel 6 and Above
use Illuminate\Auth\Events\Verified;
use Illuminate\Http\Request;
use App\User;
// comment auth middleware
//$this->middleware('auth');
public function verify(Request $request)
{
$user = User::find($request->route('id'));
if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
throw new AuthorizationException;
}
if ($user->markEmailAsVerified())
event(new Verified($user));
return redirect($this->redirectPath())->with('verified', true);
}
Бесполезно: точно такой же код, как в принятом ответе, и добавлен после последнего редактирования.
Вот более перспективное решение проблемы:
class VerificationController extends Controller
{
// …
use VerifiesEmails {
verify as originalVerify;
}
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth'); // DON'T REMOVE THIS
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
/**
* Mark the authenticated user's email address as verified.
*
* @param Request $request
* @return Response
*
* @throws AuthorizationException
*/
public function verify(Request $request)
{
$request->setUserResolver(function () use ($request) {
return User::findOrFail($request->route('id'));
});
return $this->originalVerify($request);
}
}
Поэтому, когда неаутентифицированный пользователь нажимает ссылку для подтверждения по электронной почте, происходит следующее:
1 На этом этапе электронное письмо не будет помечено как подтвержденное.
2 Пользователь может вводить неверные учетные данные несколько раз. Как только он введет правильные учетные данные, он будет перенаправлен на предполагаемый URL-адрес подтверждения электронной почты.
Однако трейт VerifyEmails был удален в Laravel 7.x.
Я получаю при этом «Сначала необходимо подтвердить свой адрес электронной почты».
Не следует удалять $this->middleware('auth') полностью, так как это повлияет на перенаправления. Если вы удалите его, неаутентифицированные пользователи будут перенаправлены на «/ email / verify» вместо «/ login».
поэтому $this->middleware('auth'); будет заменен на $this->middleware('auth')->except('verify'); в "VerificationController"
Также скопируйте функцию «verify» из «VerifyEmails» в «VerificationController».
добавьте эти две строки кода вверху функции
$user = User::find($request->route('id'));
auth()->login($user);
поэтому вы программно входите в систему, а затем выполняете дальнейшие действия
Решение для разрешения проверки электронной почты для пользователей, которые не вошли в систему (т.е. без авторизации):
Изменения в: app / Http / Controllers / Auth / VerificationController.php:
$this->middleware('auth'); в $this->middleware('auth')->except('verify');verify() из признака VerifiesEmails.$request->user().Мой метод verify() в VerificationController выглядит так:
public function verify(\Illuminate\Http\Request $request)
{
$user = User::find($request->route('id'));
if ($request->route('id') != $user->getKey()) {
throw new AuthorizationException;
}
if ($user->markEmailAsVerified())
event(new Verified($user));
return redirect()->route('login')->with('verified', true);
}
Подписанное промежуточное ПО
Laravel использует промежуточное ПО с именем signed для проверки целостности URL-адресов, сгенерированных приложением. Подписано проверяет, был ли изменен URL-адрес с момента его создания. Попробуйте изменить идентификатор, время истечения срока действия или подпись в URL-адресе, и это приведет к ошибке - очень эффективное и полезное промежуточное ПО для защиты метода verify ()
Для получения дополнительной информации: https://laravel.com/docs/8.x/urls#signed-urls
(По желанию)
Я перенаправил своих пользователей на маршрут входа, а не на предполагаемый маршрут по двум причинам. 1) После входа в систему он пытался перенаправить пользователя на ссылку для подтверждения адреса электронной почты, что приводило к ошибке; 2) Я хотел использовать проверенные истинные флэш-данные, которые были прикреплены к перенаправлению, чтобы отображать предупреждение на странице входа в систему, если пользователь успешно подтвердил свой адрес электронной почты.
Пример моего предупреждения на странице входа:
@if (session()->has('verified'))
<div class = "alert alert-success">Your email address has been successfully verified.</div>
@endif
Предложения
Если у вас есть предложения по улучшению этого кода, дайте мне знать. Я был бы счастлив отредактировать этот ответ.
Вот мой взгляд на ситуацию. Проверка требует, чтобы пользователь вошел в систему, прежде чем он сможет завершить проверку, поэтому мы можем переопределить функцию проверки и войти в систему, используя идентификатор, который мы получили в ссылке. Это безопасная причина, по которой функция проверки не вызывается, если Laravel не может проверить подпись из URL-адреса, поэтому, даже если кто-то изменит URL-адрес, он не сможет его обойти.
Перейдите в свой VerificationController и добавьте следующую функцию в конец файла.
public function verify(Request $request)
{
if (!auth()->check()) {
auth()->loginUsingId($request->route('id'));
}
if ($request->route('id') != $request->user()->getKey()) {
throw new AuthorizationException;
}
if ($request->user()->hasVerifiedEmail()) {
return redirect($this->redirectPath());
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect($this->redirectPath())->with('verified', true);
}
Примечание
Убедитесь, что для параметра same_site в config / session.php установлено значение lax. Если для него установлено значение «строгий», сеанс не будет сохраняться, если вы были перенаправлены с другого сайта. Например, если вы щелкнете ссылку подтверждения из Gmail, ваш файл cookie сеанса не будет сохраняться, поэтому он не будет перенаправлять вас на панель управления, но установит поле «email_verified_at» в базе данных, помечая проверку как успешную. Пользователь не поймет, что произошло, потому что это перенаправит пользователя на страницу входа. Если вы установили для него значение «строгий», он будет работать, если вы скопируете ссылку для подтверждения прямо в адресную строку браузера, но не если пользователь щелкнет ссылку в веб-клиенте Gmail, поскольку он использует перенаправление для отслеживания ссылки.
хорошая попытка. работает как положено для меня. Благодарность
Почему вы хотите этого? Теперь я могу просто передать это электронное письмо и захватить любую учетную запись.