如何在Angular 7与ASP.NET Web API中实现ValidateAntiForgeryToken?
没问题,我之前做过Web API+Angular的防伪造令牌实现,给你整理了极简的可运行示例,分服务端和客户端两部分:
服务端(ASP.NET Web API)实现
注意:默认的ValidateAntiForgeryTokenAttribute是为MVC设计的,Web API不能直接用,所以我们需要自定义过滤器
1. 配置Antiforgery服务(Startup.cs)
using System.Web.Helpers; using System.Web.Http; using System.Web.Mvc; public class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); // 配置用户标识(如果是认证用户,用这个关联令牌) AntiForgeryConfig.UniqueClaimTypeIdentifier = System.Security.Claims.ClaimTypes.NameIdentifier; // 注册Web API路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); app.UseWebApi(config); } }
2. 自定义Web API防伪造令牌过滤器
using System.Linq; using System.Net; using System.Net.Http; using System.Web.Helpers; using System.Web.Http.Controllers; using System.Web.Http.Filters; public class ValidateAntiForgeryTokenApiAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { // 从请求头获取令牌 var headers = actionContext.Request.Headers; if (headers.Contains("X-XSRF-TOKEN")) { var tokenHeader = headers.GetValues("X-XSRF-TOKEN").FirstOrDefault(); try { // 匿名用户第一个参数传null,认证用户传用户标识 AntiForgery.Validate(null, tokenHeader); } catch { actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "无效的防伪造令牌"); return; } } else { actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "缺少防伪造令牌"); } base.OnActionExecuting(actionContext); } }
3. 控制器使用示例
using System.Web.Helpers; using System.Web.Http; [RoutePrefix("api/antiforgery")] public class AntiForgeryController : ApiController { // 供客户端获取令牌的接口 [HttpGet] [Route("gettoken")] public IHttpActionResult GetToken() { // 匿名用户传null,认证用户传用户ID等唯一标识 var token = AntiForgery.GetToken(null); return Ok(new { XsrfToken = token }); } // 需要验证令牌的POST接口 [HttpPost] [Route("test")] [ValidateAntiForgeryTokenApi] public IHttpActionResult Test([FromBody] string data) { return Ok($"收到数据: {data}"); } }
客户端(Angular 7)实现
1. 封装防伪造令牌服务
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class AntiForgeryService { private xsrfToken: string | null = null; private baseApiUrl = 'https://你的API地址/api'; constructor(private http: HttpClient) { // 初始化时自动获取令牌 this.fetchXsrfToken().subscribe(token => { this.xsrfToken = token; }); } private fetchXsrfToken(): Observable<string> { return this.http.get<{ XsrfToken: string }>(`${this.baseApiUrl}/antiforgery/gettoken`) .pipe(map(response => response.XsrfToken)); } // 自动携带令牌的POST请求封装 postRequest<T>(endpoint: string, body: any): Observable<T> { const requestHeaders = new HttpHeaders({ 'X-XSRF-TOKEN': this.xsrfToken || '' }); return this.http.post<T>(`${this.baseApiUrl}/${endpoint}`, body, { headers: requestHeaders }); } }
2. 组件中使用示例
import { Component } from '@angular/core'; import { AntiForgeryService } from './anti-forgery.service'; @Component({ selector: 'app-root', template: `<button (click)="sendTestRequest()">发送测试请求</button>` }) export class AppComponent { constructor(private antiForgeryService: AntiForgeryService) {} sendTestRequest() { this.antiForgeryService.postRequest<string>('antiforgery/test', 'Hello Web API') .subscribe( response => console.log('请求成功:', response), error => console.error('请求失败:', error) ); } }
额外提示:如果是跨域场景,需要在服务端配置CORS,允许X-XSRF-TOKEN请求头通过
内容的提问来源于stack exchange,提问作者Batsheva
相关产品推荐
相关产品推荐

