Laavel의 PasswordBroker 조사
26309 단어 LaravelPHPpasswordbrokertech
이번에는 라벨의 5.3부터 조금 구조적으로 들어간 패스워드브로커를 소스의 수준으로 조사했다.
버전 확인
Laavel8의 PasswordBroker 설치가 확인되었습니다.
실제 설치와 5 계열 때는 큰 변화가 없었다.
도대체 PasswordBroker가 뭐예요?
매번 라벨의 이름은 일본인들이 이해하기 어려워요...
브로커는 중개인이라는 뜻이 있는 것 같아요.실제 코드를 읽으면 이해하기 쉬우나 비밀번호 리셋 처리의 절차는 이PasswordBroker를 통해 진행된다.
다음은 PasswordBroker가 할 일입니다.
PasswordBroker 만드는 법
PasswordBroker
는 PasswordResetServiceProvider
→PasswordManager
→PasswordBroker
느낌으로 3개 반을 통해 제작됐다.PasswordBroker
구조기로서 두 개의 매개 변수가 있다./**
* Create a new password broker instance.
*
* @param \Illuminate\Auth\Passwords\TokenRepositoryInterface $tokens
* @param \Illuminate\Contracts\Auth\UserProvider $users
* @return void
*/
public function __construct(TokenRepositoryInterface $tokens,
UserProvider $users)
{
$this->users = $users;
$this->tokens = $tokens;
}
UserProvider
는 Auth에서도 자주 사용하는 물건이다.TokenRepositoryInterface
이름처럼 비밀번호 토큰의 창고죠.현재
DatabaseTokenRepository
실현TokenRepositoryInterface
.(이 Token Repository Interface는 흔히 볼 수 있는 창고 모델로서의 실현은 참고 가치가 있다고 생각한다.)PasswordBrokerManager의 역할
PasswordBrokerManager
의 역할은 명칭과 같이 관리이다.여러 브로커를 관리할 수 있습니다. 호출할 때 생성되지 않으면 config에 따라 실례를 생성하고 되돌려줍니다.
흔한 실크룩입니다.
public function broker($name = null)
{
$name = $name ?: $this->getDefaultDriver();
return $this->brokers[$name] ?? ($this->brokers[$name] = $this->resolve($name));
}
Token 만들기
우선 영패의 기초 제작을 살펴보자.
다음은 PasswordBroker의 방법입니다.
/**
* Create a new password reset token for the given user.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return string
*/
public function createToken(CanResetPasswordContract $user)
{
return $this->tokens->create($user);
}
Token Repository Interface라는 create.실제로 DatabaseToken Repository는 이렇습니다.
/**
* Create a new token record.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return string
*/
public function create(CanResetPasswordContract $user)
{
// パスワードリセットに利用するメールアドレスを取得
$email = $user->getEmailForPasswordReset();
// tokenが入ってるテーブルに対象ユーザ(email)のデータがあったら消す
$this->deleteExisting($user);
// ランダムなトークンを生成します。
$token = $this->createNewToken();
$this->getTable()->insert($this->getPayload($email, $token));
return $token;
}
그럼 삽입할 때getPayload
방법을 살펴봅시다./**
* Build the record payload for the table.
*
* @param string $email
* @param string $token
* @return array
*/
protected function getPayload($email, $token)
{
return ['email' => $email, 'token' => $this->hasher->make($token), 'created_at' => new Carbon];
}
토큰을 산열하여 넣습니다.안전의식이 있는 실장입니다.실제 DB를 볼 수 있는 사람도 남용하지 않도록 데이터를 산열했다.
암호를 재설정할 때 원본 영패를 링크에 끼워 넣고 산열하여 비교 검사를 합니다.
PasswordBroker:sendResetLink 처리
가장 많이 사용할 수 있는sendResetLink 처리를 살펴보겠습니다.
/**
* Send a password reset link to a user.
*
* @param array $credentials
* @param \Closure|null $callback
* @return string
*/
public function sendResetLink(array $credentials, Closure $callback = null)
{
// ユーザを取得
$user = $this->getUser($credentials);
if (is_null($user)) {
return static::INVALID_USER;
}
// 最近作られたトークンがあるか(Throttleに引っかかるか)
if ($this->tokens->recentlyCreatedToken($user)) {
return static::RESET_THROTTLED;
}
$token = $this->tokens->create($user);
if ($callback) {
$callback($user, $token);
} else {
// 通知を発火する
$user->sendPasswordResetNotification($token);
}
return static::RESET_LINK_SENT;
}
getUser 처리
중요한 것은 이 두 줄이다.
// 受け取ったcredentialsからtokenを除く(理由はfindに引っかからない可能性があるため)
$credentials = Arr::except($credentials, ['token']);
// 主にemail情報を元にUser情報を取得する
$user = $this->users->retrieveByCredentials($credentials);
// あとは存在しなかった場合のエラー処理、返り値はuser。
$this->tokens->recentlyCreatedToken의 처리
나는 처음에는 이 처리를 잘 몰랐다.
간단하게 설명하자면throttling(기본 60초)을 설정하면 이전에 작성한 기록
追加日時+throttling秒
과 現在日時
을 비교한다.public function recentlyCreatedToken(CanResetPasswordContract $user)
{
$record = (array) $this->getTable()->where(
'email', $user->getEmailForPasswordReset()
)->first();
return $record && $this->tokenRecentlyCreated($record['created_at']);
}
protected function tokenRecentlyCreated($createdAt)
{
if ($this->throttle <= 0) {
return false;
}
return Carbon::parse($createdAt)->addSeconds(
$this->throttle
)->isFuture(); // isFutureは未来かどうか
}
즉 이 처리가 설정된throttle의 초 이내에 호출되었는지 판단하는 것이다.결과는 다음과 같은 처리에서 탄착되었다.
if ($this->tokens->recentlyCreatedToken($user)) {
return static::RESET_THROTTLED;
}
처리 방법
마지막으로 메일만 보냈어요.
Illuminate\Auth\Passwords\CanResetPassword
TRAIT를 사용하는 경우 다음 절차를 수행합니다.이것에 관해서는 사용자 클래스에서 단독으로 실현할 수 있다.
/**
* Send the password reset notification.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
이 notify 방법은trait의 방법이다.저라면 모델 내
Notifiable
에 TRAIT를 사용했기 때문notify
방법RoutesNotifications
TRAIT 방법입니다.sendPasswordResetNotification
메서드도 Illuminate\Auth\Passwords\CanResetPassword
TRAIT에서 호출된 경우CanResetPassword::sendResetNotification
→ Userクラス
→ Notifiableトレイト
→ RoutesNotifications::notify
전화번호가 어떻게 되세요?public function notify($instance) // ResetPasswordNotificationインスタンスが入ってくる
{
app(Dispatcher::class)->send($this, $instance);
}
여기서부터는 일반 노티픽션과 같다.ResetPasswordNotification
클래스에 toMail
방법이 설치되어 있어 메일 발송 방법으로 호출되었습니다.PasswordBroker:sendResetLink 반환 값 정보
반환된 값은 상태입니다.
실제 사용하는 코드는 다음과 같은 느낌을 가지고 있다.
return $status == Password::RESET_LINK_SENT
? app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status])
: app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]);
총결산
이렇게 하면 PasswordBroker가 완성됩니다.
잘 처리한 게 Token Repository인 것 같은데.hasher를 통해 throttle, token을 DB에 넣는 것 같은 거.
그럼 안녕히 계세요.
Reference
이 문제에 관하여(Laavel의 PasswordBroker 조사), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/fagai/articles/d9188458766a7ecdfda9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)