افزودن و اعتبارسنجی خودکار Anti-Forgery Tokens در برنامه‌های Angular مبتنی بر ASP.NET Core
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: پنج دقیقه

Anti-forgery tokens یک مکانیزم امنیتی، جهت مقابله با حملات CSRF هستند. در برنامه‌های ASP.NET Core، فرم‌های دارای Tag Helper مانند asp-controller و asp-action به صورت خودکار دارای یک فیلد مخفی حاوی این token، به همراه تولید یک کوکی مخصوص جهت تعیین اعتبار آن خواهند بود. البته در برنامه‌های ASP.NET Core 2.0 تمام فرم‌ها، چه حاوی Tag Helpers باشند یا خیر، به همراه درج این توکن تولید می‌شوند.
برای مثال در برنامه‌های ASP.NET Core، یک چنین فرمی:
<form asp-controller="Manage" asp-action="ChangePassword" method="post">   
   <!-- Form details --> 
</form>
به صورت ذیل رندر می‌شود که حاوی قسمتی از Anti-forgery token است و قسمت دیگر آن در کوکی مرتبط درج می‌شود:
<form method="post" action="/Manage/ChangePassword">   
  <!-- Form details --> 
  <input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkSldwD9CpLR...LongValueHere!" /> 
</form>
در این مطلب چگونگی شبیه سازی این عملیات را در برنامه‌های Angular که تمام تبادلات آن‌ها Ajax ایی است، بررسی خواهیم کرد.


تولید خودکار کوکی‌های Anti-forgery tokens برای برنامه‌های Angular

در سمت Angular، مطابق مستندات رسمی آن (^ و ^)، اگر کوکی تولید شده‌ی توسط برنامه، دارای نام مشخص «XSRF-TOKEN» باشد، کتابخانه‌ی HTTP آن به صورت خودکار مقدار آن‌را استخراج کرده و به درخواست بعدی ارسالی آن اضافه می‌کند. بنابراین در سمت ASP.NET Core تنها کافی است کوکی مخصوص فوق را تولید کرده و به Response اضافه کنیم. مابقی آن توسط Angular به صورت خودکار مدیریت می‌شود.
می‌توان اینکار را مستقیما داخل متد Configure کلاس آغازین برنامه انجام داد و یا بهتر است جهت حجیم نشدن این فایل و مدیریت مجزای این مسئولیت، یک میان‌افزار مخصوص آن‌را تهیه کرد:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace AngularTemplateDrivenFormsLab.Utils
{
    public class AntiforgeryTokenMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IAntiforgery _antiforgery;

        public AntiforgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery)
        {
            _next = next;
            _antiforgery = antiforgery;
        }

        public Task Invoke(HttpContext context)
        {
            var path = context.Request.Path.Value;
            if (path != null && !path.StartsWith("/api/", StringComparison.OrdinalIgnoreCase))
            {
                var tokens = _antiforgery.GetAndStoreTokens(context);
                context.Response.Cookies.Append(
                      key: "XSRF-TOKEN",
                      value: tokens.RequestToken,
                      options: new CookieOptions
                      {
                          HttpOnly = false // Now JavaScript is able to read the cookie
                      });
            }
            return _next(context);
        }
    }

    public static class AntiforgeryTokenMiddlewareExtensions
    {
        public static IApplicationBuilder UseAntiforgeryToken(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<AntiforgeryTokenMiddleware>();
        }
    }
}
توضیحات تکمیلی:
- در اینجا ابتدا سرویس IAntiforgery به سازنده‌ی کلاس میان افزار تزریق شده‌است. به این ترتیب می‌توان به سرویس توکار تولید توکن‌های Antiforgery دسترسی یافت. سپس از این سرویس جهت دسترسی به متد GetAndStoreTokens آن برای دریافت محتوای رشته‌ای نهایی این توکن استفاده می‌شود.
- اکنون که به این توکن دسترسی پیدا کرده‌ایم، تنها کافی است آن‌را با کلید مخصوص XSRF-TOKEN که توسط Angular شناسایی می‌شود، به مجموعه‌ی کوکی‌های Response اضافه کنیم.
- علت تنظیم مقدار خاصیت HttpOnly به false، این است که کدهای جاوا اسکریپتی Angular بتوانند به مقدار این کوکی دسترسی پیدا کنند.

پس از تدارک این مقدمات، کافی است متد الحاقی کمکی UseAntiforgeryToken فوق را به نحو ذیل به متد Configure کلاس آغازین برنامه اضافه کنیم؛ تا کار نصب میان افزار AntiforgeryTokenMiddleware، تکمیل شود:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
   app.UseAntiforgeryToken();


پردازش خودکار درخواست‌های ارسالی از طرف Angular

تا اینجا برنامه‌ی سمت سرور ما کوکی‌های مخصوص Angular را با کلیدی که توسط آن شناسایی می‌شود، تولید کرده‌است. در پاسخ، Angular این کوکی را در هدر مخصوصی به نام «X-XSRF-TOKEN» به سمت سرور ارسال می‌کند (ابتدای آن یک X اضافه‌تر دارد).
به همین جهت به متد ConfigureServices کلاس آغازین برنامه مراجعه کرده و این هدر مخصوص را معرفی می‌کنیم تا دقیقا مشخص گردد، این توکن از چه قسمتی باید جهت پردازش استخراج شود:
public void ConfigureServices(IServiceCollection services)
{
      services.AddAntiforgery(x => x.HeaderName = "X-XSRF-TOKEN");
      services.AddMvc();
}

یک نکته: اگر می‌خواهید این کلیدهای هدر پیش فرض Angular را تغییر دهید، باید یک CookieXSRFStrategy سفارشی را برای آن تهیه کنید.


اعتبارسنجی خودکار Anti-forgery tokens در برنامه‌های ASP.NET Core

ارسال کوکی اطلاعات Anti-forgery tokens و سپس دریافت آن توسط برنامه، تنها یک قسمت از کار است. قسمت بعدی، بررسی معتبر بودن آن‌ها در سمت سرور است. روش متداول انجام اینکار‌، افزودن ویژگی [ValidateAntiForgeryToken]  به هر اکشن متد مزین به [HttpPost] است:
  [HttpPost] 
  [ValidateAntiForgeryToken] 
  public IActionResult ChangePassword() 
  { 
    // ... 
    return Json(…); 
  }
هرچند این روش کار می‌کند، اما در ASP.NET Core، فیلتر توکار دیگری به نام AutoValidateAntiForgeryToken نیز وجود دارد. کار آن دقیقا همانند فیلتر ValidateAntiForgeryToken است؛ با این تفاوت که از حالت‌های امنی مانند GET و HEAD صرفنظر می‌کند. بنابراین تنها کاری را که باید انجام داد، معرفی این فیلتر توکار به صورت یک فیلتر سراسری است، تا به تمام اکشن متدهای HttpPost برنامه به صورت خودکار اعمال شود:
public void ConfigureServices(IServiceCollection services)
{
       services.AddAntiforgery(x => x.HeaderName = "X-XSRF-TOKEN");
       services.AddMvc(options =>
       {
           options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
       });
}
به این ترتیب دیگر نیازی نیست تا ویژگی ValidateAntiForgeryToken را به تک تک اکشن متدهای از نوع HttpPost برنامه به صورت دستی اعمال کرد.

یک نکته: در این حالت بررسی سراسری، اگر در موارد خاصی نیاز به این اعتبارسنجی خودکار نبود، می‌توان از ویژگی [IgnoreAntiforgeryToken] استفاده کرد.


آزمایش برنامه

برای آزمایش مواردی را که تا کنون بررسی کردیم، همان مثال «فرم‌های مبتنی بر قالب‌ها در Angular - قسمت پنجم - ارسال اطلاعات به سرور» را بر اساس نکات متدهای ConfigureServices و Configure مطلب جاری تکمیل می‌کنیم. سپس برنامه را اجرا می‌کنیم:


همانطور که ملاحظه می‌کنید، در اولین بار درخواست برنامه، کوکی مخصوص Angular تولید شده‌است.
در ادامه اگر فرم را تکمیل کرده و ارسال کنیم، وجود هدر ارسالی از طرف Angular مشخص است و همچنین خروجی هم با موفقیت دریافت شده‌است:



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: angular-template-driven-forms-lab-09.zip
برای اجرای آن فرض بر این است که پیشتر Angular CLI را نصب کرده‌اید. سپس به ریشه‌ی پروژه وارد شده و دو پنجره‌ی کنسول مجزا را باز کنید. در اولی دستورات
>npm install
>ng build --watch
و در دومی دستورات ذیل را اجرا کنید:
>dotnet restore
>dotnet watch run
اکنون می‌توانید برنامه را در آدرس http://localhost:5000 مشاهده و اجرا کنید.
  • #
    ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۹:۲۱
    زمانیکه در برنامه این موارد رو اعمال میکنم  درخواست هایی که دارای هدر Authorization  باشند با خطای زیر مواجه میشوند: 

    Antiforgery token validation failed. The provided antiforgery token was meant for a different claims-based user than the current user.
    اما برای درخواست‌های فاقد هدر Authorization این مشکل وجود ندارد.
    • #
      ‫۶ سال و ۶ ماه قبل، پنجشنبه ۱۷ اسفند ۱۳۹۶، ساعت ۰۳:۱۶
      - برای اولین باری که برنامه بارگذاری می‌شود، یک anti-forgery token تولید خواهد شد. پس از لاگین، این توکن به اطلاعات شخص متصل می‌شود. در حین logout دیگر این توکن قابلیت استفاده‌ی مجدد را ندارد و خطای فوق را دریافت می‌کنید. به همین جهت اگر logout به صورت POST انجام می‌شود، آن‌را تبدیل به GET کنید؛ از این جهت که HttpClient نگارش 4.3 به بعد اگر یکی از شرایط زیر برقرار باشد (درخواست‌های از نوع GET یا HEAD و یا آدرس‌های مطلق)، این هدر را ارسال نمی‌کند و همچنین AutoValidateAntiforgeryTokenAttribute سمت سرور هم به درخواست‌های از نوع GET واکنش نشان نمی‌دهد:
      const lcUrl = request.url.toLowerCase();
      if (request.method === "GET" || request.method === "HEAD" ||
                lcUrl.startsWith("http://") || lcUrl.startsWith("https://")) {
                // skip
      }

      چند نکته‌ی تکمیلی:
      - برای یک چنین حالت‌هایی، خصوصا حالت آدرس‌های مطلق (برنامه در یک زیر پوشه اجرا شود)، نیاز است یک interceptor سفارشی ایجاد کرد.
      - سفارشی سازی نام کوکی و هدر در HttpClient توسط HttpClientXsrfModule انجام می‌شود:
       imports: [   HttpClientModule,  
         HttpClientXsrfModule.withConfig({
           cookieName: 'My-Xsrf-Cookie',
           headerName: 'My-Xsrf-Header'
         }) ]
  • #
    ‫۶ سال و ۵ ماه قبل، دوشنبه ۲۰ فروردین ۱۳۹۷، ساعت ۰۴:۰۶
    وقتی که یک فرم با متد POST به سمت API ارسال میشه خطای 400 Bad request می‌گیرم.
    ولی اگر AutoValidateAntiforgeryTokenAttribute در قسمت سرویس startup رو غیر فعال می‌کنم مشکل پیش نمیاد.
    درصورتی که برای فرم لاگین با همچین مشکلی برخورد نمی‌کنم!
    • #
      ‫۶ سال و ۵ ماه قبل، سه‌شنبه ۲۱ فروردین ۱۳۹۷، ساعت ۲۳:۴۹
      پاسخ دادن به این سؤال بدون مطالعه‌ی سورس https://github.com/aspnet/Antiforgery غیرممکن است. علت اینکه روش توضیح داده شده‌ی در این مطلب، برای حالت برنامه‌های دارای اعتبارسنجی کار نمی‌کند و خطای «The provided antiforgery token was meant for a different claims-based user than the current user» را دریافت می‌کنید، این صورت است:
       میان‌افزار طراحی شده‌ی در این مطلب، پیش از لاگین و با اولین درخواست تک صفحه‌ی برنامه، کوکی‌های antiforgery را دریافت می‌کند. اما ... سیستم antiforgery طوری طراحی شده‌است که پیش از تولید کوکی، مشخصات دقیق this.HttpContext.User را دریافت و هش می‌کند (لیست Claims آن‌را به صورت رشته در می‌آورد و هش SHA256 آن را محاسبه می‌کند). از این هش هم جهت تولید محتوای کوکی نهایی خود استفاده می‌کند. بنابراین در بار اولی که صفحه درخواست شده‌است، یک کوکی antiforgery مخصوص کاربر null و اعتبارسنجی نشده، تولید خواهد شد. بعد از آن پس از لاگین، اگر میان‌افزار یاد شده مجددا نیز فراخوانی شود، هیچ اتفاق خاصی رخ نخواهد داد. از این جهت که در طراحی متد GetAndStoreTokens آن، به ازای یک صفحه، فقط یکبار این کوکی تولید می‌شود و اگر هزار بار دیگر هم این متد را جهت برنامه‌ی تک صفحه‌ای خود فراخوانی کنیم، به این معنا نخواهد بود که مشخصات this.HttpContext.User را به کوکی جدیدی اضافه می‌کند؛ چون اصلا کوکی جدیدی را تولید نمی‌کند!

      بنابراین راه حل نهایی به این صورت است:
      الف) میان افزار AngularAntiforgeryTokenMiddleware فوق را حذف کنید. این میان‌افزار عملا کاربردی برای برنامه‌های SPA دارای اعتبارسنجی ندارد.
      ب) امضای متد Login را به این صورت تغییر دهید که شامل IgnoreAntiforgeryToken باشد:
      [AllowAnonymous]
      [IgnoreAntiforgeryToken]
      [HttpPost("[action]")]
      public async Task<IActionResult> Login([FromBody] User loginUser)
      از این جهت که نمی‌توانیم پیش از لاگین، درخواست تولید کوکی antiforgery را برای کاربر null صادر کنیم؛ چون این کوکی تا پایان عمر مرورگر تغییری نخواهد کرد.
      ج) در متد لاگین، پس از تولید توکن‌ها، اکنون کار تولید کوکی را به صورت زیر انجام می‌دهیم:
      private void regenerateAntiForgeryCookie(IEnumerable<Claim> claims)
      {
          this.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme));
          var tokens = _antiforgery.GetAndStoreTokens(this.HttpContext);
          this.HttpContext.Response.Cookies.Append(
                        key: "XSRF-TOKEN",
                        value: tokens.RequestToken,
                        options: new CookieOptions
                        {
                            HttpOnly = false // Now JavaScript is able to read the cookie
                        });
      }
      در این‌جا لیست claims ایی را که در حین تولید توکن‌ها ایجاد کردیم، تبدیل به یک ClaimsPrincipal می‌کنیم تا بتوانیم this.HttpContext.User را مقدار دهی کنیم (دقیقا با مشخصات اصلی کاربر لاگین شده) و سپس متد GetAndStoreTokens را فراخوانی می‌کنیم تا این User غیرنال را خوانده و کوکی صحیحی را تولید کند. به این صورت است که دیگر پیام خطای «این antiforgery توکن، متعلق به کاربر دیگری است» را دریافت نخواهیم کرد. این «کاربر دیگر» منظورش همان کاربر null ابتدای کار است که پیش از لاگین تنظیم می‌شد و با کاربر جدیدی که دارای claims است یکی نبود.

      نکته‌ی مهم! جائیکه Claim‌های برنامه را تولید می‌کنید، باید حتما Issuer را هم ذکر کنید:
       new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString(),
                        ClaimValueTypes.String, _configuration.Value.Issuer),
      از این جهت که هش SHA256 ایی که توضیح داده شده، بر اساس این Issuer، مقدار و نوع Claim محاسبه می‌شود. اگر Issuer را ذکر نکنید، به local authority تنظیم می‌شود که با Issuer نهایی توکن تولید شده یکی نیست. به همین جهت حتی اگر this.HttpContext.User را هم مقدار دهی کنید، کار نمی‌کند؛ چون هش claim‌های تولیدی، یکی نخواهند بود و باز هم پیام «این antiforgery توکن متعلق به کاربر دیگری است» را دریافت خواهید کرد.


      خلاصه این تغییرات به پروژه‌ی ASPNETCore2JwtAuthentication اعمال شده‌اند.
      • #
        ‫۶ سال و ۵ ماه قبل، جمعه ۲۴ فروردین ۱۳۹۷، ساعت ۱۷:۰۰
        در صورتیکه AccessToken منقضی گردد توسط RefreshToken آپدیت می‌شود اگر پس از آپدیت محتویات claim به هر دلیلی تغییر کند (مثلا نقشی حذف یا اضافه گردد) باید مجددا متد regenerateAntiForgeryCookie  در اکشن RefreshToken فراخوانی گردد؟
        • #
          ‫۶ سال و ۵ ماه قبل، جمعه ۲۴ فروردین ۱۳۹۷، ساعت ۱۷:۰۹
          برای دیباگ این موضوع متد DefaultClaimUidExtractor.GetUniqueIdentifierParameters(this.User.Identities) را مستقلا روی لیست Claims جدید فراخوانی کنید. اگر محتوای آن با قبلی تفاوت داشت، همان پیام خطای «این antiforgery توکن، متعلق به کاربر دیگری است» را دریافت خواهید کرد.
        • #
          ‫۶ سال و ۵ ماه قبل، جمعه ۲۴ فروردین ۱۳۹۷، ساعت ۱۸:۰۵
          برای اینکه برنامه بیش از اندازه پیچیده نشود، بهتر است کوکی‌های مربوطه در حین Logout حذف شوند و سپس کاربر لاگین کند. یک نمونه پیاده سازی آن
          • #
            ‫۶ سال و ۵ ماه قبل، جمعه ۲۴ فروردین ۱۳۹۷، ساعت ۲۳:۵۸
            در این حالت زمانیکه برنامه دارای فرم ثبت نام باشد و بخواهیم از  Anti-forgery tokens در فرم ثبت نام استفاده کنیم باید cookie جداگانه ای برای این فرم ایجاد کنیم؟
  • #
    ‫۶ سال و ۲ ماه قبل، سه‌شنبه ۱۲ تیر ۱۳۹۷، ساعت ۲۱:۵۵
    سلام
    من از ASP. Net Web API 2  برای سرویس هام استفاده می‌کنم، برای سمت Front از Angular 6
    چطور میتونم Anti-Forgery Token رو توش پیاده سازی کنم، متاسفانه مطلب مفیدی پیدا نکردم که کمک کنه. (نمونه همین مورد رو با AngularJS پیاده کردم، ولی ظاهرا اینجا یه کم متفاوت هست)
    ممنون میشم راهنمایی کنید
    • #
      ‫۶ سال و ۲ ماه قبل، چهارشنبه ۱۳ تیر ۱۳۹۷، ساعت ۱۵:۱۰
      یک چنین پیاده سازی خواهد داشت:
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Net.Http;
      using System.Web;
      using System.Web.Helpers;
      using System.Web.Http.Controllers;
      using System.Web.Http.Filters;
      using System.Web.Mvc;
      using ActionFilterAttribute = System.Web.Http.Filters.ActionFilterAttribute;
      
      namespace NgxAntiforgeryWebApi.Providers
      {
          public class XsrfCookieGeneratorAttribute : ActionFilterAttribute
          {
              public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
              {
                  var xsrfTokenCookie = new HttpCookie("XSRF-TOKEN")
                  {
                      Value = ComputeXsrfTokenValue(),
                      HttpOnly = false // Now JavaScript is able to read the cookie
                  };
                  HttpContext.Current.Response.AppendCookie(xsrfTokenCookie);
              }
      
              private string ComputeXsrfTokenValue()
              {
                  string cookieToken, formToken;
                  AntiForgery.GetTokens(null, out cookieToken, out formToken);
                  return $"{cookieToken}:{formToken}";
              }
          }
      
          public class XsrfTokensValidationAttribute : ActionFilterAttribute
          {
              public override void OnActionExecuting(HttpActionContext actionContext)
              {
                  IEnumerable<string> headerValues;
                  if (!actionContext.Request.Headers.TryGetValues("X-XSRF-TOKEN", out headerValues))
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = "X-XSRF-TOKEN header is missing." };
                      return;
                  }
      
                  if (headerValues == null)
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = "X-XSRF-TOKEN header value is empty." };
                      return;
                  }
      
                  var xsrfTokensValue = headerValues.FirstOrDefault();
                  if (string.IsNullOrEmpty(xsrfTokensValue) || !xsrfTokensValue.Contains(":"))
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = "X-XSRF-TOKEN header value is null." };
                      return;
                  }
      
                  var values = xsrfTokensValue.Split(':');
                  if (values.Length != 2)
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = "X-XSRF-TOKEN header value is malformed." };
                      return;
                  }
      
                  var cookieToken = values[0];
                  var formToken = values[1];
      
                  try
                  {
                      AntiForgery.Validate(cookieToken, formToken);
                  }
                  catch (HttpAntiForgeryException ex)
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest) {  ReasonPhrase = ex.Message };
                  }
              }
          }
      }
      XsrfCookieGeneratorAttribute کار تولید کوکی مخصوص Angular را انجام می‌دهد (می‌تواند به عنوان فیلتر سراسری معرفی شود و یا فقط یکبار پس از لاگین، کوکی آن‌را به روشی که عنوان شده، تولید کنید؛ بدون نیاز به تولید هرباره‌ی آن با هر درخواستی) و XsrfTokensValidationAttribute بجای ValidateAntiForgeryToken اصلی بکار خواهد رفت.
      • #
        ‫۶ سال و ۲ ماه قبل، چهارشنبه ۱۳ تیر ۱۳۹۷، ساعت ۱۷:۴۸
        ممنون از راهنماییتون

        موارد رو انجام دادم، با توجه به جدا بودن دامین API و FRONT یه مشکلی برخورد کردم. 
        با زدن درخواست کوکی XSRF-TOKEN ساخته میشه، ولی وقتی درخواست POST میزنم X-XSRF-TONEK توی هدر درخواست اضافه نمیشه
        - XsrfInterceptor رو اضافه کردم، توی Module برنامه تعاریف رو انجام دادم
        - سمت سرور اومدم کوکی رو به صورت زیر تغییر دادم:
        var xsrfTokenCookie = new HttpCookie("XSRF-TOKEN")
        {
             Value = ComputeXsrfTokenValue(),
             HttpOnly = false, // Now JavaScript is able to read the cookie
             Path = "/",
             Domain = "localhost"
        };
        - Cross Origin رو متناسب با دامنه فعال کردم
        - حتی از طریق proxy.config آدرس API رو ست کردم
        ولی متاسفانه باز جوابی نگرفتم. میخواستم ببینم نکته ای وجود داره که رعایت نکرده باشم در این زمینه؟
        • #
          ‫۶ سال و ۲ ماه قبل، چهارشنبه ۱۳ تیر ۱۳۹۷، ساعت ۱۸:۳۵
          در سمت Angular برای ارسال کوکی‌ها بین دومین‌ها باید withCredentials: true تنظیم شود:
          this.http
              .post<Xyz>(`${this.apiUrl}`, data, { withCredentials: true /* For CORS */ })
              .map(response => response || {})
              .catch(this.handleError);
          و یا می‌توانید یک HTTP Interceptor برای آن بنویسید تا نیازی به ذکر دستی آن نباشد:
          @Injectable()
          export class CORSInterceptor implements HttpInterceptor {
          
              constructor() {}
          
              intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
                  request = request.clone({
                      withCredentials: true
                  });
                  return next.handle(request);
              }
          }
      • #
        ‫۶ سال و ۲ ماه قبل، چهارشنبه ۱۳ تیر ۱۳۹۷، ساعت ۱۷:۵۶
        با عرض پوزش مشکل رو برطرف کردم، از اطلاعات فایل پروکسیم بود، به اینصورت مقدار دهی کردم
        {
          "/api": {
             "target":  {
               "host": "localhost",
               "protocol": "http:",
               "port": 8357
             },
             "secure": false,
             "changeOrigin": true,
             "logLevel": "info"
          }
        }

  • #
    ‫۱ سال و ۵ ماه قبل، یکشنبه ۱۴ اسفند ۱۴۰۱، ساعت ۱۳:۰۰
    سلام وقت بخیر
    من یه مشکل دارم اینه که وقتی تابع لاگین رو فراخوانی میکنم کوکی‌ها رو تولید میکنه و در ریسپانس ، توکن‌ها رو دریافت میکنه ولی ذخیره نمیشه در صورتی که یه تابع تستی GET درست کردم و RegenerateAntiForgeryCookies  رو فراخوانی کردم و مستقیم تو مرورگر زدم و اینبار کوکی‌ها ذخیره شده به نظرتون کجای کار من اشتباه بوده