Laravel 9密码确认中间件功能不起作用

huangapple go评论95阅读模式
英文:

Laravel 9 password.confirm middleware feature not working

问题

我正在尝试在我的一些需要安全保护的路由中使用password.confirm中间件。我希望用户在生成特定的POST请求时应该确认他的密码。

此外,password.confirm中间件已添加到app/Http/Kernel.php文件的$routeMiddleware属性中。

这是我的web.php中路由的样子。

  1. Route::post('fetchResult', [ReportController::class, 'fetchResult'])->name('fetchComplaintResult')->middleware('password.confirm');

但它不起作用。当我生成POST请求时,它直接命中到控制器的fetchResult方法,与往常一样。

我的控制器函数:

  1. public function fetchResult(Request $request)
  2. {
  3. Model::create([
  4. 'id' => $request->id,
  5. 'action' => $request->action,
  6. 'comments' => $request->comment
  7. ]);
  8. // 其他操作
  9. }

我是否遗漏了什么?

英文:

I am trying to use the password.confirm middleware in some of my routes which I need to be secured. I want a user should confirm his password when he generate a specific post request.

Also, password.confirm middleware is added $routeMiddleware property in the app/Http/Kernel.php file.

This is what my route looks like in web.php.

  1. Route::post('fetchResult', [ReportController::class, 'fetchResult'])->name('fetchComplaintResult')->middleware('password.confirm');

But it is not working. When I generate post request it directly hit to controller fetchResult method as usual.

My controller function:

  1. public function fetchResult(Request $request)
  2. {
  3. Model::create([
  4. 'id' => $request->id,
  5. 'action' => $request->action,
  6. 'comments' => $request->comment
  7. ]);
  8. // Other Action
  9. }

Am I missing something ??

答案1

得分: 2

如果你想在每次需要确认密码时得到提示,你应该像这样编写你的路由:

  1. Route::post('fetchResult', [ReportController::class, 'fetchResult'])
  2. ->name('fetchComplaintResult')
  3. ->middleware('password.confirm:password.confirm,1');

为什么?

password.confirm 中间件映射到 Illuminate\Auth\Middleware\RequirePassword 类。以下是它的代码。

  1. use Closure;
  2. use Illuminate\Contracts\Routing\ResponseFactory;
  3. use Illuminate\Contracts\Routing\UrlGenerator;
  4. class RequirePassword
  5. {
  6. /**
  7. * The response factory instance.
  8. *
  9. * @var \Illuminate\Contracts\Routing\ResponseFactory
  10. */
  11. protected $responseFactory;
  12. /**
  13. * The URL generator instance.
  14. *
  15. * @var \Illuminate\Contracts\Routing\UrlGenerator
  16. */
  17. protected $urlGenerator;
  18. /**
  19. * The password timeout.
  20. *
  21. * @var int
  22. */
  23. protected $passwordTimeout;
  24. /**
  25. * 创建一个新的中间件实例。
  26. *
  27. * @param \Illuminate\Contracts\Routing\ResponseFactory $responseFactory
  28. * @param \Illuminate\Contracts\Routing\UrlGenerator $urlGenerator
  29. * @param int|null $passwordTimeout
  30. * @return void
  31. */
  32. public function __construct(ResponseFactory $responseFactory, UrlGenerator $urlGenerator, $passwordTimeout = null)
  33. {
  34. $this->responseFactory = $responseFactory;
  35. $this->urlGenerator = $urlGenerator;
  36. $this->passwordTimeout = $passwordTimeout ?: 10800;
  37. }
  38. /**
  39. * 处理传入的请求。
  40. *
  41. * @param \Illuminate\Http\Request $request
  42. * @param \Closure $next
  43. * @param string|null $redirectToRoute
  44. * @param int|null $passwordTimeoutSeconds
  45. * @return mixed
  46. */
  47. public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null)
  48. {
  49. if ($this->shouldConfirmPassword($request, $passwordTimeoutSeconds)) {
  50. if ($request->expectsJson()) {
  51. return $this->responseFactory->json([
  52. 'message' => 'Password confirmation required.',
  53. ], 423);
  54. }
  55. return $this->responseFactory->redirectGuest(
  56. $this->urlGenerator->route($redirectToRoute ?? 'password.confirm')
  57. );
  58. }
  59. return $next($request);
  60. }
  61. /**
  62. * 确定确认超时是否已过期。
  63. *
  64. * @param \Illuminate\Http\Request $request
  65. * @param int|null $passwordTimeoutSeconds
  66. * @return bool
  67. */
  68. protected function shouldConfirmPassword($request, $passwordTimeoutSeconds = null)
  69. {
  70. $confirmedAt = time() - $request->session()->get('auth.password_confirmed_at', 0);
  71. return $confirmedAt > ($passwordTimeoutSeconds ?? $this->passwordTimeout);
  72. }
  73. }

需要注意的重要部分是 handle 方法的签名:

  1. public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null)

在这里,$redirectToRoute$passwordTimeoutSeconds 是我们可以在路由文件中设置的参数。

$redirectToRoutehandle 方法中像这样使用:

  1. $this->urlGenerator->route($redirectToRoute ?? 'password.confirm')

$passwordTimeoutSecondsshouldConfirmPassword 方法中使用:

  1. return $confirmedAt > ($passwordTimeoutSeconds ?? $this->passwordTimeout);

由于它被设置为 null,所以与之比较的值是 $this->passwordTimeout,它在构造函数中被设置为 10800(10800 秒 = 180 分钟 = 3 小时)。

因此,总结一下,我们需要设置 $passwordTimeoutSeconds 参数。由于它是第二个参数,我们还需要设置 $redirectToRoute 参数。

更多信息,请参考 Laravel 文档

英文:

If you want to get prompted to confirm your password every time you should write your route like this:

  1. Route::post('fetchResult', [ReportController::class, 'fetchResult'])
  2. ->name('fetchComplaintResult')
  3. ->middleware('password.confirm:password.confirm,1');

Why?

The password.confirm middleware maps to the Illuminate\Auth\Middleware\RequirePassword class. This is its code.

  1. use Closure;
  2. use Illuminate\Contracts\Routing\ResponseFactory;
  3. use Illuminate\Contracts\Routing\UrlGenerator;
  4. class RequirePassword
  5. {
  6. /**
  7. * The response factory instance.
  8. *
  9. * @var \Illuminate\Contracts\Routing\ResponseFactory
  10. */
  11. protected $responseFactory;
  12. /**
  13. * The URL generator instance.
  14. *
  15. * @var \Illuminate\Contracts\Routing\UrlGenerator
  16. */
  17. protected $urlGenerator;
  18. /**
  19. * The password timeout.
  20. *
  21. * @var int
  22. */
  23. protected $passwordTimeout;
  24. /**
  25. * Create a new middleware instance.
  26. *
  27. * @param \Illuminate\Contracts\Routing\ResponseFactory $responseFactory
  28. * @param \Illuminate\Contracts\Routing\UrlGenerator $urlGenerator
  29. * @param int|null $passwordTimeout
  30. * @return void
  31. */
  32. public function __construct(ResponseFactory $responseFactory, UrlGenerator $urlGenerator, $passwordTimeout = null)
  33. {
  34. $this->responseFactory = $responseFactory;
  35. $this->urlGenerator = $urlGenerator;
  36. $this->passwordTimeout = $passwordTimeout ?: 10800;
  37. }
  38. /**
  39. * Handle an incoming request.
  40. *
  41. * @param \Illuminate\Http\Request $request
  42. * @param \Closure $next
  43. * @param string|null $redirectToRoute
  44. * @param int|null $passwordTimeoutSeconds
  45. * @return mixed
  46. */
  47. public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null)
  48. {
  49. if ($this->shouldConfirmPassword($request, $passwordTimeoutSeconds)) {
  50. if ($request->expectsJson()) {
  51. return $this->responseFactory->json([
  52. 'message' => 'Password confirmation required.',
  53. ], 423);
  54. }
  55. return $this->responseFactory->redirectGuest(
  56. $this->urlGenerator->route($redirectToRoute ?? 'password.confirm')
  57. );
  58. }
  59. return $next($request);
  60. }
  61. /**
  62. * Determine if the confirmation timeout has expired.
  63. *
  64. * @param \Illuminate\Http\Request $request
  65. * @param int|null $passwordTimeoutSeconds
  66. * @return bool
  67. */
  68. protected function shouldConfirmPassword($request, $passwordTimeoutSeconds = null)
  69. {
  70. $confirmedAt = time() - $request->session()->get('auth.password_confirmed_at', 0);
  71. return $confirmedAt > ($passwordTimeoutSeconds ?? $this->passwordTimeout);
  72. }
  73. }

The important parts to note are the handle method's signature:

  1. public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null)

Here, $redirectToRoute and $passwordTimeoutSeconds are arguments we can set in the route file.

$redirectToRoute is used like this in the handle method:

  1. $this->urlGenerator->route($redirectToRoute ?? 'password.confirm')

$passwordTimeoutSeconds is used here in the shouldConfirmPassword method.

  1. return $confirmedAt > ($passwordTimeoutSeconds ?? $this->passwordTimeout);

Since it's set to null, the value $confirmedAt is compared to is $this->passwordTimeout, which is set in the constructor to 10800. (10800 seconds = 180 minutes = 3 hours).

So in summary we need to set the $passwordTimeoutSeconds parameter. Since it's the second parameter, we also need to set the $redirectToRoute parameter.

https://laravel.com/docs/9.x/middleware#middleware-parameters

huangapple
  • 本文由 发表于 2023年2月6日 15:04:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75358255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定