2014-01-21 19 views
31

asp.net mvc webapiをバックエンドとクライアント側のルーティング(cshtmlなし)として使用して、SPAのanglejsアプリケーションで認証と認可の例を作成します。以下は、完全な例を設定するために使用できる関数の例です。しかし、私はそれをすべてtogehterにすることはできません。どんな助けもありがたい。webapiを使用したAngularJSクライアント側のルーティングとトークンの認証

質問:

  1. のベストプラクティスは何をされています。クッキーまたはトークンベースの?
  2. 各リクエストで承認するために、どのように角度でベアラトークンを作成しますか?
  3. API関数の検証?
  4. クライアントで署名されたユーザーの認証を保持するにはどうすればよいですか?

例コード:

<form name="form" novalidate> 
<input type="text" ng-model="user.userName" /> 
<input type="password" ng-model="user.password" /> 
<input type="submit" value="Sign In" data-ng-click="signin(user)"> 
</form> 
  • 認証角度コントローラ

    $scope.signin = function (user) { 
    $http.post(uri + 'account/signin', user) 
        .success(function (data, status, headers, config) { 
         user.authenticated = true; 
         $rootScope.user = user; 
         $location.path('/'); 
        }) 
        .error(function (data, status, headers, config) { 
    
         alert(JSON.stringify(data)); 
         user.authenticated = false; 
         $rootScope.user = {}; 
        }); 
    }; 
    
  • マイAPIバックエンドのAPIコード形式で

    1. サインインします。コンテンツを制限するためのJWTライブラリを使用して

      [HttpPost] 
      public HttpResponseMessage SignIn(UserDataModel user) 
      { 
          //FormsAuthetication is just an example. Can I use OWIN Context to create a session and cookies or should I just use tokens for authentication on each request? How do I preserve the autentication signed in user on the client? 
          if (this.ModelState.IsValid) 
          { 
           if (true) //perform authentication against db etc. 
           { 
            var response = this.Request.CreateResponse(HttpStatusCode.Created, true); 
            FormsAuthentication.SetAuthCookie(user.UserName, false); 
      
            return response; 
           } 
      
           return this.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Invalid username or password"); 
          } 
          return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState); 
      } 
      
    2. 認証 。

      config.MessageHandlers.Add(new JsonWebTokenValidationHandler 
      { 
          Audience = "123", 
          SymmetricKey = "456" 
      }); 
      
    3. 私のAPIメソッド

      [Authorize] 
      public IEnumerable<string> Get() 
      { 
      return new string[] { "value1", "value2" }; 
      } 
      
  • 答えて

    89

    クッキー認証または(ベアラ)を使用するかどうかをあなたが持っているアプリの種類によって異なり、まだトークン。そして、私が知る限り、まだベストプラクティスはありません。しかし、あなたがSPAで作業しており、すでにJWTライブラリを使用しているので、私はトークンベースのアプローチに賛成です。

    残念ながら、私はASP.NETであなたを助けることはできませんが、通常はJWTライブラリがトークンを生成して確認します。資格情報(および秘密情報)にはgenerateまたはencodeを、トークンにはすべての要求と一緒にverifyまたはdecodeとしてください。サーバーに状態を保存する必要はなく、FormsAuthentication.SetAuthCookie(user.UserName, false)でおそらく行ったことがある、クッキーを送信する必要はありません。

    私はあなたのライブラリが生成/エンコードと検証/デコードトークンの使用方法の例を提供していると確信しています。

    したがって、生成と検証はクライアント側で行うものではありません。

    流れはこのような何かを行く:

    1. クライアントがサーバーにユーザー提供のログイン資格情報を送信します。
    2. サーバーは、資格情報を認証し、生成されたトークンで応答します。
    3. クライアントは、トークンをどこかに格納します(ローカルストレージ、Cookie、またはメモリ内にのみ)。
    4. クライアントは、要求ごとに承認ヘッダーとしてトークンをサーバーに送信します。
    5. サーバーは、トークンを検証し、要求されたリソースまたは401(または同様のもの)を送信することによって、適切に動作します。

    ステップ1と3は:

    app.controller('UserController', function ($http, $window, $location) { 
        $scope.signin = function(user) { 
        $http.post(uri + 'account/signin', user) 
         .success(function (data) { 
          // Stores the token until the user closes the browser window. 
          $window.sessionStorage.setItem('token', data.token); 
          $location.path('/'); 
         }) 
         .error(function() { 
          $window.sessionStorage.removeItem('token'); 
          // TODO: Show something like "Username or password invalid." 
         }); 
        }; 
    }); 
    

    sessionStorage限り、ユーザーが開いているページを持っているとしてデータを保持します。有効期限を自分で処理したい場合は、代わりにlocalStorageを使用できます。インターフェイスは同じです。

    ステップ4:

    サーバへのリクエストごとにトークンを送信するには、角度がInterceptor呼ぶものを使用することができます。

    app.factory('AuthInterceptor', function ($window, $q) { 
        return { 
         request: function(config) { 
          config.headers = config.headers || {}; 
          if ($window.sessionStorage.getItem('token')) { 
           config.headers.Authorization = 'Bearer ' + $window.sessionStorage.getItem('token'); 
          } 
          return config || $q.when(config); 
         }, 
         response: function(response) { 
          if (response.status === 401) { 
           // TODO: Redirect user to login page. 
          } 
          return response || $q.when(response); 
         } 
        }; 
    }); 
    
    // Register the previously created AuthInterceptor. 
    app.config(function ($httpProvider) { 
        $httpProvider.interceptors.push('AuthInterceptor'); 
    }); 
    

    、常にSSLを使用してください:あなたがしなければならないのは、以前に格納されたトークン(もしあれば)を取得し、すべての発信要求にヘッダとしてそれを添付しています!

    +0

    本当に素晴らしい説明です。私が探していたものです。答えと詳細な例をありがとう。 –

    +0

    確かに、私は助けてうれしい:) – bernhardw

    +0

    隠しIフレーム(認証サーバーが前のアクセス許可を記憶していると仮定)によってアクセストークンを更新する方法はありますか? – g18c

    関連する問題