This commit is contained in:
Hans362 2026-03-31 09:19:58 +08:00 committed by GitHub
commit fd10a596b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 12 additions and 11 deletions

View File

@ -344,20 +344,20 @@ class AuthController extends Controller
return redirect('/user'); return redirect('/user');
} }
public function verify(Request $request) public function verify(Request $request, User $user)
{ {
if (!option('require_verification')) { if (!option('require_verification')) {
throw new PrettyPageException(trans('user.verification.disabled'), 1); throw new PrettyPageException(trans('user.verification.disabled'), 1);
} }
abort_unless($request->hasValidSignature(false), 403, trans('auth.verify.invalid')); abort_unless($request->hasValidSignature(false) && hash_equals((string)$request->route('hash'), hash('sha256', $user->email)), 403, trans('auth.verify.invalid'));
return view('auth.verify'); return view('auth.verify');
} }
public function handleVerify(Request $request, User $user) public function handleVerify(Request $request, User $user)
{ {
abort_unless($request->hasValidSignature(false), 403, trans('auth.verify.invalid')); abort_unless($request->hasValidSignature(false) && hash_equals((string)$request->route('hash'), hash('sha256', $user->email)), 403, trans('auth.verify.invalid'));
['email' => $email] = $request->validate(['email' => 'required|email']); ['email' => $email] = $request->validate(['email' => 'required|email']);

View File

@ -157,7 +157,7 @@ class UserController extends Controller
return json(trans('user.verification.verified'), 1); return json(trans('user.verification.verified'), 1);
} }
$url = URL::signedRoute('auth.verify', ['user' => $user], null, false); $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false);
try { try {
Mail::to($user->email)->send(new EmailVerification(url($url))); Mail::to($user->email)->send(new EmailVerification(url($url)));

View File

@ -4,6 +4,7 @@ namespace App\Listeners;
use App\Mail\EmailVerification; use App\Mail\EmailVerification;
use App\Models\User; use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\URL;
@ -12,7 +13,7 @@ class SendEmailVerification
public function handle(User $user) public function handle(User $user)
{ {
if (option('require_verification')) { if (option('require_verification')) {
$url = URL::signedRoute('auth.verify', ['user' => $user->uid], null, false); $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false);
try { try {
Mail::to($user->email)->send(new EmailVerification(url($url))); Mail::to($user->email)->send(new EmailVerification(url($url)));

View File

@ -41,8 +41,8 @@ Route::prefix('auth')->name('auth.')->group(function () {
Route::post('bind', 'AuthController@fillEmail')->name('verify'); Route::post('bind', 'AuthController@fillEmail')->name('verify');
}); });
Route::get('verify/{user}', 'AuthController@verify')->name('verify'); Route::get('verify/{user}/{hash}', 'AuthController@verify')->name('verify');
Route::post('verify/{user}', 'AuthController@handleVerify')->name('handle.verify'); Route::post('verify/{user}/{hash}', 'AuthController@handleVerify')->name('handle.verify');
}); });
Route::prefix('user') Route::prefix('user')

View File

@ -724,7 +724,7 @@ class AuthControllerTest extends TestCase
public function testVerify() public function testVerify()
{ {
$url = URL::signedRoute('auth.verify', ['user' => 1], null, false); $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => 1, 'hash' => hash('sha256', 'a@b.c')], false);
// should be forbidden if account verification is disabled // should be forbidden if account verification is disabled
option(['require_verification' => false]); option(['require_verification' => false]);
@ -732,17 +732,17 @@ class AuthControllerTest extends TestCase
option(['require_verification' => true]); option(['require_verification' => true]);
// invalid link // invalid link
$this->get(route('auth.verify', ['user' => 1]))->assertForbidden(); $this->get(route('auth.verify', ['user' => 1, 'hash' => hash('sha256', 'a@b.c')]))->assertForbidden();
$user = User::factory()->create(['verified' => false]); $user = User::factory()->create(['verified' => false]);
$url = URL::signedRoute('auth.verify', ['user' => $user], null, false); $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false);
$this->get($url)->assertViewIs('auth.verify'); $this->get($url)->assertViewIs('auth.verify');
} }
public function testHandleVerify() public function testHandleVerify()
{ {
$user = User::factory()->create(['verified' => false]); $user = User::factory()->create(['verified' => false]);
$url = URL::signedRoute('auth.verify', ['user' => $user], null, false); $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false);
// empty email // empty email
$this->post($url, [], ['Referer' => $url])->assertRedirect($url); $this->post($url, [], ['Referer' => $url])->assertRedirect($url);