簡體   English   中英

如何使用 NET 6 在 Angular 中實現 AntiForgery 令牌

[英]How to implement AntiForgery Token in Angular with NET 6

我正在處理幾個關於使用 angular 實現防偽令牌的過時文檔。 就我而言,我在沒有 MVC Razor 的情況下工作,只有 angular 13.3.4 和 NET 6.0

我只是進行配置:

builder.Services.AddAntiforgery(options =>
{
    options.HeaderName = "X-XSRF-TOKEN";
});

builder.Services.AddScoped<AntiforgeryMiddleware>();

然后是控制器:

public class AntiforgeryMiddleware : IMiddleware
    {
        private readonly IAntiforgery _antiforgery;

        public AntiforgeryMiddleware(IAntiforgery antiforgery)
        {
            _antiforgery = antiforgery;
        }

        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            var isGetRequest = string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase);
            if (!isGetRequest)
            {
                _antiforgery.ValidateRequestAsync(context).GetAwaiter().GetResult();
            }

            await next(context);
        }
    }

但仍然無法得到有角度的東西。 我的帖子是這個(只是為了測試它):

import { Component, Inject } from '@angular/core';
import { HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpXSRFInterceptor } from 'src/app/interceptors/tok.interceptor';

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: HttpXSRFInterceptor, multi: true }
]

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
  public lenormandjack: LenormandHand = {} as LenormandHand;

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string, ) {
    http.post<LenormandHand>(baseUrl + 'api/lenormand', null, { withCredentials: true }).subscribe(result => {
      this.lenormandjack = result;
      console.dir(result);
      console.log("OK");
      console.dir(this.lenormandjack);
    }, error => console.error(error));
  }
}

我正在學習角度,我無法獲得甚至可以編譯為打字稿的代碼。 完全被阻止,並且多次(數十次)搜索中的文檔返回相同。 或者只是為了 WebApi。

我正在嘗試使用此控制器進行防偽工作:

[HttpPost]
[ValidateAntiForgeryToken]
public LenormandHand Post()
{
    return foobar;
 
}

我的攔截器:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpXsrfTokenExtractor } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";

@Injectable()
export class XsrfInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) { }

  private actions: string[] = ["POST", "PUT", "DELETE"];
  private forbiddenActions: string[] = ["HEAD", "OPTIONS"];

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let token = this.tokenExtractor.getToken();
    console.log ("TOKEN: "+token);
    let permitted = this.findByActionName(request.method, this.actions);
    let forbidden = this.findByActionName(request.method, this.forbiddenActions);;

    if (permitted !== undefined && forbidden === undefined && token !== null) {
      request = request.clone({ setHeaders: { "X-XSRF-TOKEN": token } });
    }

    return next.handle(request);
  }

  private findByActionName(name: string, actions: string[]): string | undefined {
    return actions.find(action => action.toLocaleLowerCase() === name.toLocaleLowerCase());
  }
}

任何幫助都會受到重視,評論,問題,答案,任何東西。 提前致謝

更新:

在此之后: 使用令牌 API 和 Angular 進行防偽我可以編譯,但答案是 400 bad request。 在深層,包含 X-XSRF-TOKEN 的標頭始終為 false

終於做到了。 有很多變化(而不是),但是為了安全地實現這一點,您必須考慮很多因素。

我將列舉並制作一個教程,因為我浪費了很多時間來解決這個請求/問題。

The question itself I made is fine, so you can the code for the answer from the question itself.

  • 甚至不要嘗試“控制器方式”來生成令牌。 是無意義的,因為每個人都可以調用它。

  • 調用應具有以下 cookie 選項:

     Path = "/", HttpOnly = false, Secure = true, SameSite = SameSiteMode.Strict
  • 設置只需要:

這個:

builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");  

和這個:

app.UseAntiforgeryToken();
  • 重金屬部分:調用不應該是絕對的:

我在這里使用“api”,因為我只想用“api”保護控制器,所以我可以選擇什么和不做什么。

 constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string, ) {
    http.post<yourclass>(baseUrl + 'api/controller', null, { withCredentials: true }).subscribe(result => {
      this.yourinstance = result;
    }, error => console.error(error));
  }
}
  • app.module.ts文件中

添加這個:

import { XsrfInterceptor } from 'src/app/interceptors/tok.interceptor';

然后在@NgModule @NgModule({部分:

  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor, multi: true }
  ],

總共喜歡:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';

import { XsrfInterceptor } from 'src/app/interceptors/tok.interceptor';


@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full' },
      { path: 'counter', component: CounterComponent },
      { path: 'fetch-data', component: FetchDataComponent },
    ])
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • 如果您只想將它​​用於某種控制器,我還用“api”前綴將它們分開:

所以我的控制器有這個:

[ApiController]
[Route("api/[controller]")]

我的方法是這樣的:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public Method Post()
    {

因此,您可以進行 Invoke 檢查路徑是否具有 api。 到處都有這個實現的幾個例子,因為它是針對 web api 的。 根據 gusto e piacere,這完全是可選的。

  • 如果您處於使用反向代理的開發模式,如果您使用與我相同的方法,請不要忘記將“api”添加到代理設置。

您將其添加到proxy.config.js

const PROXY_CONFIG = [
  {
    context: [
      "/imgs",
      "/api"
   ],

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM