2015-12-18 11 views
6

デフォルトのLaravel authを調整して、AngularJSのAPIとして機能させることができました。/reset/{token}に行くパスワードリセットリンクが付いた電子メールを送信してもらえます。また、検証エラーがなければ、パスワードは正常に変更されます。Laravel 5.1/AngularJS:Angular Viewでパスワードをリセットする(CSRFトークンを検証する方法)

私は角度表示を使用しているので、唯一の問題は、実際にトークンを検証することがなく、reset-password状態を示す前にちょっとばかげていないことを確認することではありません。私は、コントローラの先頭にこれを追加してみました:

if ($stateParams.token != $cookies.get('XSRF_TOKEN')) { 
     $state.go('reset'); 
    } 

...トークンは、現在のCSRFトークンであれば基本的に見るだろうが、パスワードリセットのリンクがCSRF送信されたときので、それは動作しません。トークンが変更されたり、セッションからのトークンではなくなりました。

私はこれをどのように行うことができますか? `/ reset /:token 'のURLに入力されたトークンが有効でない場合、ユーザーをリダイレクトしたいだけです。これはResetsPassword.phpでResetsPasswordの特性である

 .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' 
     }) 

:ここ

は私のコードは...

App.jsです。ほとんどが既に設定されていましたが、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(); 
    } 

答えて

5

似たような問題を抱えている人のために...ここで私はそれをどのように解決したのでしょうか(おそらく後でもっとうまくいくでしょうが、今のところうまくいきます)。

私はreset/passwordというAPIの別のURLを追加し、GETリクエストを受け取りました。私はそれに$stateParams値に基づいてトークンを渡し、そのトークンがpassword_resetsテーブルに存在しない場合、またはそのトークンが存在し、有効期限が切れている場合は、いくつかのエラーを返します。コントローラでは、私はリダイレクトでエラーを処理します。再びこれは理想的ではないと思います。ソースを見て誰かがそれを変更してリダイレクトを削除するので、これを実装するためのより良い方法を見つけなければならないからです。

しかし、今のところそれは機能していますが、解決策です。

ResetsPasswords.php(get要求のための方法を追加しました):

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で、私はちょうどrespose戻って「成功」または「エラー」応答のいずれかどうかを確認し、それは私がちょうど$state.go('reset')のようなものをやって "パスワードを忘れた"フォームに戻って、パスワードをリセットするリンクを得るために電子メールを入力するような "エラー"応答の場合です。

EDIT:

私はそれは常に一瞬のために、少なくともビューをロードするためのコントローラで有効なトークンをチェックすることは悪かったことを考え出しました。何らかのミドルウェアを探していましたが、私はすでに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' 
      }) 

は、それが同じ問題で誰にもお役に立てば幸いです。

+0

これは、LaravelとAngularを使用して開発しているすべての人にとって便利な質問です。投稿していただきありがとうございます。 – delatbabel

関連する問題