Laravel 5.1/AngularJS:在 Angular 视图中重置密码(如何验证 CSRF 令牌?)
Posted
技术标签:
【中文标题】Laravel 5.1/AngularJS:在 Angular 视图中重置密码(如何验证 CSRF 令牌?)【英文标题】:Laravel 5.1/AngularJS: Reset password in Angular view (how to validate CSRF token?) 【发布时间】:2016-03-24 16:43:30 【问题描述】:我设法调整了默认的 Laravel 身份验证,以便它可以作为我的 AngularJS 的 API 工作,到目前为止一切正常。可以转到 /reset 并输入一封电子邮件,然后会收到一封带有密码重置链接的电子邮件,该链接转到 /reset/token,如果您没有收到任何验证错误,您的密码将成功更改。
唯一的问题是,由于我使用的是 Angular 视图,因此在显示 reset-password
状态之前,实际上没有任何东西可以验证令牌并确保它不仅仅是胡言乱语。我尝试将其添加到控制器的顶部:
if ($stateParams.token != $cookies.get('XSRF_TOKEN'))
$state.go('reset');
...这基本上会查看令牌是否是当前的 CSRF 令牌,但这不起作用,因为当发送密码重置链接时,CSRF 令牌已更改或其他...它不再是来自的令牌会议。
有人知道我该怎么做吗?如果在 `/reset/:token' 的 url 中输入的令牌无效,我只想重定向用户。
这是我的代码..
App.js:
.state('reset',
url: '/reset',
data:
permissions:
except: ['isLoggedIn'],
redirectTo: 'user.dashboard'
,
templateUrl: 'views/auth/forgot-password.html',
controller: 'ForgotPasswordController as forgot'
)
.state('reset-password',
url: '/reset/:token',
data:
permissions:
except: ['isLoggedIn'],
redirectTo: 'user.dashboard'
,
templateUrl: 'views/auth/reset-password.html',
controller: 'ResetPasswordController as reset'
)
这在 ResetsPassword.php 的 ResetsPassword 特征中。大多数已经设置好了,但我删除/更改了很多以作为 API 工作:
/**
* Send a reset link to the given user.
*/
public function postEmail(EmailRequest $request)
$response = Password::sendResetLink($request->only('email'), function (Message $message)
$message->subject($this->getEmailSubject());
);
switch ($response)
case Password::RESET_LINK_SENT:
return;
case Password::INVALID_USER:
return response()->json([
'denied' => 'We couldn\'t find your account with that information.'
], 404);
/**
* Get the e-mail subject line to be used for the reset link email.
*/
protected function getEmailSubject()
return property_exists($this, 'subject') ? $this->subject : 'Your Password Reset Link';
/**
* Reset the given user's password.
*/
public function postReset(ResetRequest $request)
$credentials = $request->only(
'password', 'password_confirmation', 'token'
);
$response = Password::reset($credentials, function ($user, $password)
$this->resetPassword($user, $password);
);
switch ($response)
case Password::PASSWORD_RESET:
return;
default:
return response()->json([
'error' => [
'message' => 'Could not reset password'
]
], 400);
/**
* Reset the given user's password.
*/
protected function resetPassword($user, $password)
$user->password = bcrypt($password);
$user->save();
【问题讨论】:
【参考方案1】:想通了。
对于遇到类似问题的任何人...这是我解决它的方法(以后可能会变得更好,但现在它可以工作)。
我为 API 添加了另一个 URL,它是 reset/password
,它需要一个 GET 请求。我根据$stateParams
值将令牌传递给它,如果password_resets
表中不存在该令牌,或者如果该令牌确实存在并且已过期,则返回一些错误。在控制器中,我通过重定向处理错误。同样,我认为这并不理想,因为任何查看源代码的人都可以更改它并删除重定向,所以我必须找到更好的方法来实现它。
但是,现在它仍然有效,但它仍然是一个解决方案。
ResetsPasswords.php(为获取请求添加了一个方法):
public function verifyToken(Request $request)
$user = DB::table('password_resets')->where('token', $request->only('token'))->first();
if ($user)
if ($user->created_at > Carbon::now()->subHours(2))
return response()->json([
'success' => [
'message' => 'Token is valid and not expired.'
]
], 200);
else
return response()->json([
'error' => [
'message' => 'Token is valid but it\'s expired.'
]
], 401);
else
return response()->json([
'error' => [
'message' => 'Token is invalid.'
]
], 401);
在我的 resetPasswordController.js 中,我只检查响应是否返回“成功”或任何“错误”响应,如果是“错误”响应,我将执行类似 $state.go('reset')
的操作,将它们重定向回来到“忘记密码”表单,他们在其中输入电子邮件以获取重置密码链接。
编辑:
我认为在控制器中检查有效令牌是不好的,因为它总是会加载视图至少一瞬间。我一直在寻找某种中间件,但后来我忘记了我已经在使用 angular-permission 包,它充当前端中间件。
我定义了一个角色isTokenValid
并对其进行了设置,以便它自动调用我拥有的 authService 中的一个函数,并根据令牌的有效性从我的 API 获得响应。如果成功,则角色允许用户进入状态。否则它会重定向到reset
状态。这可以防止在瞬间显示视图。行为与 Laravel 中间件非常相似。
唯一的问题是,由于它发生在前端,任何黑客都可以绕过它,但这没关系,因为服务器端代码仍然存在,因此即使他们访问视图,他们也无法对输入的密码执行任何操作令牌仍然无效,必须与特定用户匹配。
另一个改进是找到一种方法来禁止视图,即使没有前端中间件实现。如果我找到办法,也许我会再次更新。
实施
角色:
.defineRole('isTokenValid', function(stateParams)
var token = stateParams.token;
var deferred = $q.defer();
authService.verifyToken(token)
.then(function(res)
if (res.success)
deferred.resolve();
, function(res)
if (res.error)
deferred.reject();
);
return deferred.promise;
);
还有状态:
.state('reset-password',
url: '/reset/:token',
data:
permissions:
only: ['isTokenValid'],
redirectTo: 'reset'
,
templateUrl: 'views/auth/reset-password.html',
controller: 'ResetPasswordController as reset'
)
希望对遇到同样问题的人有所帮助。
【讨论】:
对于使用 Laravel 和 Angular 开发的任何人来说,这是一个有用的问题和技术说明。感谢发帖。以上是关于Laravel 5.1/AngularJS:在 Angular 视图中重置密码(如何验证 CSRF 令牌?)的主要内容,如果未能解决你的问题,请参考以下文章