2016-03-29 35 views
11

Mam aplikację Angular2. Działa w zakresie ASP.NET 5 (Core).
Wykonuje wywołania Http do kontrolera, który działa poprawnie.Angular2 ASP.NET Core AntiForgeryToken

Ale teraz potrzebuję stworzyć projekcję z Cross Site Scripting.

Jak wygenerować nowy token w każdym żądaniu Http, a następnie wykonać test AntiForgeryToken w aplikacjach Angular2?

Uwaga: Moje formularze danych w Angular nie są tworzone z widoku MVC, ale są w całości napisane w Angular2 i tylko w usługach sieciowych.

Wszystkie przykłady, które widziałem są przestarzałe i nie działają/nie działają w pełni.

Jak zintegrować kontrole AntiForgeryToken w Angular2 z ASP.NET 5, gdzie formularze są czyste Angular?

Dzięki.

Odpowiedz

6

Niestandardowy filtr akcji nie jest konieczny. To wszystko może być podłączone do Startup.cs.

using Microsoft.AspNetCore.Antiforgery; 

(...) 

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); 

    (...) 
} 

public void Configure(IApplicationBuilder app, IAntiforgery antiforgery) 
{ 
    app.Use(next => context => 
    { 
    if (context.Request.Path == "/") 
    { 
     //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); 
    }); 

    (...) 
} 

Wtedy wszystko trzeba w kontrolerach jest [ValidateAntiForgeryToken] dekorator gdziekolwiek chcesz wymusić, że token jest świadczona.

Dla odniesienia, znalazłem to rozwiązanie tutaj - AspNet AntiForgery Github Issue 29.

+0

Wykonałem powyższe kroki, ale otrzymuję błąd nieprawidłowego żądania 400. Moje żądanie "post" trafia na serwer jako "opcje: typ metody". Zadałem jedno pytanie dotyczące tego problemu: https://stackoverflow.com/questions/44841588/antiforgery-token-implementation-in-angular--i-i- web-api-using-aps-net-core –

+0

Kilka dodatkowych informacji, które odkryłem dzisiaj - jeśli hostujesz w IIS, powinieneś skonfigurować Ochronę danych na serwerze w celu zachowania kluczy używanych do generowania AntiForgeryToken. Jeśli tego nie zrobisz , tokeny stracą ważność po ponownym uruchomieniu aplikacji. Zobacz tutaj, aby uzyskać informacje na temat konfiguracji - https://docs.microsoft.com/en-us/aspnet/core/publishing/iis#data-protection – DanO

0

Myślę, że należy wprowadzić niestandardowy atrybut AntiForgeryValidationToken, który obsługuje wysyłanie tokena za pośrednictwem nagłówka zamiast wartości formularza. Następnie dodaj token do nagłówka każdego żądania z aplikacji Angular2 do interfejsu API. Przykładem tutaj How do you set global custom headers in Angular2?

0

Aby potwierdzić token z nagłówka można użyć coś takiego:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
    public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentNullException(nameof(filterContext)); 
      } 

      var httpContext = filterContext.HttpContext; 
      if (httpContext.Request.Headers["__RequestVerificationToken"] == null) 
      { 
       httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; 
       httpContext.Response.StatusDescription = "RequestVerificationToken missing."; 

       filterContext.Result = new JsonResult 
       { 
        Data = new { ErrorMessage = httpContext.Response.StatusDescription }, 
        JsonRequestBehavior = JsonRequestBehavior.AllowGet 
       }; 
       return; 
      } 
      var cookie = httpContext.Request.Cookies[System.Web.Helpers.AntiForgeryConfig.CookieName]; 
      System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]); 
     } 
    } 

Następnie wystarczy dodać [ValidateHeaderAntiForgeryToken] na temat metod w kontrolerze. Pamiętaj jednak, że jest to projekt MVC 5, ASP.NET 4.5.2, więc możesz go nieco zmienić, aby dostosować się do .NET Core. Również zmodyfikowałem to, aby zwrócić wynik JSON, jeśli brakuje tokena, możesz usunąć tę część, jeśli nie wykonasz odpowiedzi na błąd i nie wyświetlisz jej użytkownikowi. Kredyty rdzeniowej części tego atrybutu idzie: https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header

Najtrudniejsze jest to, jak wygenerować AntiForgeryToken bez użycia @Html.AntiForgeryToken() w czystej Kątowymi 2 wniosku (bez dostępu do .cshtml plików). Ja również szukam odpowiedzi.

+0

Zastanawiam się, czy kiedykolwiek znalazłeś odpowiedź na pytanie, jak utworzyć token bez użycia @ Html.AntiForgeryToken()? – Jeremy

2

Używam filtra akcji do wysyłania tokenów żądania. Po prostu zastosuj to do akcji, które chcesz nowy znacznik przeciw oszustwom, np. Angular2 SPA, akcja WebAPI itp

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
public class AngularAntiForgeryTokenAttribute : ActionFilterAttribute 
{ 
    private const string CookieName = "XSRF-TOKEN"; 
    private readonly IAntiforgery antiforgery; 

    public AngularAntiForgeryTokenAttribute(IAntiforgery antiforgery) 
    { 
     this.antiforgery = antiforgery; 
    } 

    public override void OnResultExecuting(ResultExecutingContext context) 
    { 
     base.OnResultExecuting(context); 

     if (!context.Cancel) 
     { 
      var tokens = antiforgery.GetAndStoreTokens(context.HttpContext); 

      context.HttpContext.Response.Cookies.Append(
       CookieName, 
       tokens.RequestToken, 
       new CookieOptions { HttpOnly = false }); 
     } 
    } 
} 
/* HomeController */ 

[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)] 
public IActionResult Index() 
{ 
    return View(); 
} 

/* AccountController */ 

[HttpPost()] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
// Send new antiforgery token 
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)] 
public async Task<IActionResult> Register([FromBody] RegisterViewModel model) 
{ 
    //... 
    return Json(new { }); 
} 

Zarejestruj atrybut przy starcie i skonfigurować usługę zabezpieczającym do zapoznania się z prośba formularz znak "X-XSRF token" nagłówek.

public class Startup 
{ 
    // ... 

    public void ConfigureServices(IServiceCollection services) 
    { 
     // ... 

     services.AddScoped<AngularAntiForgeryTokenAttribute>(); 
     services.AddAntiforgery(options => 
     { 
      options.HeaderName = "X-XSRF-TOKEN"; 
     }); 
    } 
} 
+0

Jakieś sugestie, jak zastosować to podejście w SPA? Akcje GET praktycznie nigdy nie zostają trafione (z wyjątkiem/Home/Index), w jaki sposób dostarczyć nowy token dla każdego formularza, który spowoduje późniejszy test POST? –

+1

Spróbuj zastosować AngularAntiForgeryTokenAttribute na punktach końcowych POST. Powinieneś być w stanie odnowić token w akcjach POST. – fszlin