2017-08-21 11 views
2

現在、新しくリリースされたAsp.Net Core 2.0と特に偽造防止トークンで、Angular 4(4.3.5)でセキュリティが正しく動作するようにしています。ValidateAntiForgeryTokenがAngular 4とAsp.Net Core 2で動作するようにする

私はJavascriptServicesを使用しています.JavascriptServicesは、スターターアプリケーション(Visual Studio 2017.3のデフォルトAngularテンプレート)を提供しています。 Javascriptサービスは、.cshtmlページのAngularサイトのメインページをホストします。ユーザーがそうでないときに、/ Account/Loginの別の(非Angular)ログインページにユーザーをリダイレクトする標準フォーム認証(dot net core Identity)を使用してすべてをロックすることができるので、これは実際にはかなり有益ですログインすると、そのページにログインしてホームページにリダイレクトされ、スパが認証されたユーザーのコンテキスト内で起動して実行されます。

その作業アプリケーションはhereです。

パズルの最後の部分は、ValidateAntiForgeryToken属性を取得することです。これはAngle 4のコンテキストでは実行されていないため、Account/Loginページにログインすると問題ありません。しかし、ホームページのAngular 4内で実行しているときに、サーバーにポストバックすると、投稿がその属性が存在する場合、ValidateAntiForgeryTokenによってブロックされます。

このため、私はAccount/LogoutメソッドのValidateAntiForgeryToken属性をコメントアウトしました。これは、Angular http postを使用してサイトからログアウトしているためです。これは、属性が使用されていないときに機能しますが、使用されると失敗するかブロックされます。

Angular 4の文書に続いてhereが見つかりましたが、Angular 4が認識しているものと一致するようにAnti Whery Tokenの名前を変更しました。次のようにこれを行うために、私は、いくつかの行に追加して、私のStartup.csファイルを変更:

public void ConfigureServices(IServiceCollection services) 
{ 
      services.AddAntiforgery(options => 
      { 
       options.Cookie.Name = "XSRF-TOKEN"; 
       options.Cookie.HttpOnly = false; 
      }); 
... 
} 

これは名前角度4つのを期待してアンチ偽造クッキーにアクセスするための角度アプリを有効にする必要があります。

私のアプリでは、新しいHttpClientサービス(明らかにHttpサービスは廃止されました!)を使用するように変更しました。これはインターセプタを使用してXSRF_TOKENをサーバーに自動的に送信することになっています。

しかし、私はこの作業を行うことができませんでした。

let token = this.cookieService.get("XSRF-TOKEN"); 
console.log(token); 

var httpHeaders = new HttpHeaders({ 'XSRF-TOKEN': token }) 

this.httpClient.post(this.baseUrl + 'Account/Logout', "", { headers: httpHeaders }).subscribe(result => { 
    location.replace("/"); 
}, error => { 
    console.error(error); 
}) 
私はとして、コメントを追加ヘッダーなしの両方古いサービスを使用してみました

this.httpClient.post(this.baseUrl + 'Account/Logout', "", options).subscribe(result => { 
    location.replace("/"); 
}, error => { 
    console.error(error); 
}) 

は私が手動でヘッダを追加してみました:

私はHttpClientをサービスを使用して、標準的なポストコールを試してみました
let token = this.cookieService.get("XSRF-TOKEN"); 
     console.log(token); 

     let headers = new Headers({ 
      //'Content-Type': 'application/json', 
      'X-XSRF-TOKEN': token 
     }); 
     let options = new RequestOptions({ headers: headers }); 
     this.http.post(this.baseUrl + 'Account/Logout', "", options).subscribe(result => { 
      location.replace("/") 
     }, error => console.error(error)); 

残念ながら、私は運がありませんでした。誰かがこれを稼働させることができましたか?

答えて

0

私は解決策を見つけました。

マイIndex.cshtmlページには、次のようになります。これは何

@Html.AntiForgeryToken() 

<app>Loading...</app> 

<script src="~/dist/vendor.js" asp-append-version="true"></script> 
@section scripts { 
    <script src="~/dist/main-client.js" asp-append-version="true"></script> 
} 

は、サーバー側の偽造防止トークンを生成し、ページ上の隠し入力フィールドに配置されます。あなたはページのソースを表示すると、非表示の入力フィールドは、このようになっていること:私のログアウト方法で

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8DaEnvKVNL9EhPVzHKQWhC-PeT4eNm_svdTEyGZje4WnH34sBfG_D_AphtPzBM1JEkQUHsSX1KWBivxAOtPsOvfMKs5N_dLn0Sr3xRG-N2s0oFaa3-yvG87qdzXYm1yBSYH7dlRiBu5It3wi2iYzWqyo4B1i_iRtmikz41gmuldze8VE72zVqmeHZav5rQiHkw" /> 

、私はトークンを取得し、サーバー側のコントローラにヘッダにそれを提出します。ヘッダーの名前はRequestVerificationTokenで、アンダースコアは必要ありません。サーバー側で

Logout() { 

    let token: any = $("input[name=__RequestVerificationToken]").val(); 
    if (token !== null) { 
     var httpHeaders: any = new HttpHeaders({ 'RequestVerificationToken': token }); 

     this.httpClient.post("/Account/Logout", null, { headers: httpHeaders }).subscribe(() => { 
      window.location.replace("/Account/Login"); 
     }, error => { 
      console.log(error); 
     }); 
    } 
} 

、AntiForgeryフィルタを実行すると、送信された値と比較し、それが期待値であれば、サーバ側のアカウント/ログアウトの方法を実行することができるようになります。

サーバ側のメソッドは、次のようになります。

// 
// POST: /Account/Logout 
[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> Logout() 
{ 
    await _signInManager.SignOutAsync(); 
    return RedirectToAction(nameof(HomeController.Index), "Home"); 
} 

は、それが実行されることを証明するログアウト方法でブレークポイントを置きます。

ここには問題があるかもしれません。私は、トークンが各要求ごとに変化するかどうかはわかりません。私はこれについて何のテストもしていない。そうであれば、各要求の後に新しいトークンをページに追加する必要があります。

また、デフォルトのCookieの動作を変更する必要はありませんでした。私は角度4の方法でこれをやっていません。純粋にASP.Netのアプローチです。それはStartup.csファイル内ConfigureServices方法では、私はクッキーの変更をコメントアウトしている、次のとおりです。

public void ConfigureServices(IServiceCollection services) 
     { 
      //services.AddAntiforgery(options => 
      //{ 
      // options.Cookie.Name = "XSRF-TOKEN"; 
      // options.Cookie.HttpOnly = false; 
      //}); 

あなたがこれを行うためのより良い方法を見つけたと考えられる場合は、すべての手段によって、あなたを投稿してください溶液。

1

は、ここで同じ問題を抱えていました。私の解決策:

member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment, appLifetime : IApplicationLifetime, antiforgery : IAntiforgery) = 
let tokenMiddleware = fun (context : HttpContext) (next: Func<Task>) -> 
          let path = context.Request.Path.Value 
          if path <> null && not (path.ToLower().Contains("/api")) then 
           let tokens = antiforgery.GetAndStoreTokens(context) 
           context.Response.Cookies.Append("XSRF-TOKEN", 
            tokens.RequestToken, CookieOptions (
                  HttpOnly = false, 
                  Secure = false 
                 ) 
          ) 
          next.Invoke() 
app 
    .UseStaticFiles() 
    .UseIdentityServer() 
    .Use(tokenMiddleware) 

ここでのポイントは、それ以外のスクリプトコードがないでしょう、偽のセキュリティ保護に設定することです。そのような要求パイプライン(F番号)へのFuncを追加

  • クッキーを取得することができます。

    • は角で、私は

      login(login: UserLogin, completed:() => void, failed: (message: string) => void) { 
      const token = this.cookieService.get('XSRF-TOKEN'); 
      const httpHeaders = (token) ? new HttpHeaders({ 'X-XSRF-TOKEN': token }) : null; 
      
      this.http.post(this.apiUrl() + AccountServiceService.Login_Url, login, { headers: httpHeaders }) 
      

    が私のためにうまく動作手動でヘッダオプションを設定する必要がありました。 HIH

0

この問題は、HttpClient HttpXsrfInterceptor does not set xsrf token for absolute urlsおよびHttpClient does not set X-XSRF-Token on Http Postに関連しているようです。

私はあなたが相対URLで動作することができれば、あなたはthis.baseUrlせずに次のことを試すことができますことをお勧め:

this.httpClient.post('Account/Logout', "", options).subscribe(result => { 
    location.replace("/"); 
}, error => { 
    console.error(error); 
}) 

あなたはまた、あなたのスタートアップに以下を追加する必要があります。CSファイルは、Set-CookieのようXSRF-TOKENを渡す:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery) 
    { 
... 
app.Use(next => context => 
     { 
      if (
       string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) || 
       string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase)) 
      { 
       // We can send the request token as a JavaScript-readable cookie, and Angular will use it by default. 
       var tokens = antiforgery.GetAndStoreTokens(context); 
       context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
        new CookieOptions() { HttpOnly = false }); 
      } 

      return next(context); 
     }); 
... 

また、あなたがあなた自身のXSRFInterceptorを書いてみることができます。サンプルが表示されますhere.

関連する問題