使用Aps.Net Core在Angular 2和Web Api中实现AntiForgery Token

时间:2017-06-30 08:03:23

标签: angular asp.net-web-api asp.net-core antiforgerytoken x-xsrf-token

我在Angular 2中有单独的前端项目而没有使用MVC,而后端项目是Web Api(Asp.Net Core),它们都托管在不同的域上。我实现了AntiForgery令牌功能,但它无法正常工作。

前端项目(UI) - http://localhost:8080/

后端项目(Web Api) - http://localhost:4823/

我可以在每个请求中接收并发送XSRF-Token Cookie,但api会出现400 Bad Request错误。 我按照这个链接 - Angular2 ASP.NET Core AntiForgeryToken

Startup.cs -

public void ConfigureServices(IServiceCollection services)
{
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
    services.AddCors(options =>
    {
        options.AddPolicy("AllowAllCorsPolicy",
        builder => builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader()
                   .AllowCredentials());
     });
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IAntiforgery antiforgery)
{
    app.Use(async (context, next) =>
      {
        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 });
           }
       }
}

控制器代码 -

[EnableCors("AllowAllCorsPolicy")]
[ValidateAntiForgeryToken]
[Produces("application/json")]
[Route("api/Aoi")]
public class AoiController : Controller
{
 ...
}

角度代码 -

let options = new RequestOptions({ headers: headers, withCredentials:true });
this._http.post(this.aoiUrl, bodydata, options)
       .map((res: Response) => {
          let data = res.json();
          return data;
})

enter image description here

4 个答案:

答案 0 :(得分:0)

Cookie不能跨跨域共享。因此,即使您的web api项目将XSRF-TOKEN附加到其上下文响应,但是在单独的域中托管的前端应用程序可以使用 。通过配置AddAntiforgery()服务的选项,我看到了在两个应用程序中使用固定 cookie名称的一些变通方法。

答案 1 :(得分:0)

我认为你应该能够通过启用CORS来实现这一目标。有关详细信息,请参阅此处 - https://docs.microsoft.com/en-us/aspnet/core/security/cors

答案 2 :(得分:0)

配置Antiforgery cookie,如下所示:

service.AddAntiforgery(options =>
            {
                options.HeaderName = "X-XSRF-TOKEN";
                options.Cookie.Name = "XSRF-TOKEN";
                options.Cookie.HttpOnly = false;
                options.Cookie.Path = "/";
                options.Cookie.SameSite = SameSiteMode.None;
            });

答案 3 :(得分:0)

我最近也一直在研究此问题,并进行了一些测试,还找到了解决方法。解决方法还不错,通过使用端口,您可以使开发工作更接近于部署方案。

我发现在.Net Core Web Api应用程序中设置并启用CORS不允许您使用内置的AntiForgeryToken机制。我发现的解决方案是使用Nginx。

只需下载Nginx,然后将可执行文件和软件包放在您选择的位置。我使用C:\ nginx。

在您的位置,您将需要编辑Nginx配置文件。 (./conf/nginx.conf)

在nginx.conf文件中,您的服务器{}部分看起来与此类似:

server {
  listen: 80;
  listen: 443 ssl;
  server_name: localhost;

  #My UI Project
        location ^~ / {
            proxy_pass http://127.0.0.1:4200/;
            proxy_set_header Upgrade $http_upgrade;
            #proxy_set_header Connection 'upgrade';
            proxy_set_header Connection $http_connection;
            proxy_set_header Host $host;
            proxy_http_version 1.1;
            proxy_cache_bypass $http_upgrade;
        }

        location ^~ /sockjs-node/ {
            proxy_pass htts://127.0.0.1:4200;
            proxy_set_header Upgrade $http_upgrade;
            #proxy_set_header Connection 'upgrade';
            proxy_set_header Connection $http_connection;
            proxy_set_header Host $host;
            proxy_http_version 1.1;
            proxy_cache_bypass $http_upgrade;
        }

        #My API Project
        location ^~ /myapi/ {
            proxy_pass http://127.0.0.1:5000;
            proxy_set_header Upgrade $http_upgrade;
            #proxy_set_header Connection 'upgrade';
            proxy_set_header Connection $http_connection;
            proxy_set_header Host $host;
            proxy_http_version 1.1;
            proxy_cache_bypass $http_upgrade;
        }
}

在这里列出了我在Web服务器(例如:http://localhost)的根目录下运行的Angular UI项目(“我的UI”)

然后我们使用与Angular项目相同的网址列出sockjs-node。

最后,我列出了我的API项目(“我的Api”),并且在该位置中,添加了/myapi/路径。然后,可以从http://localhost/myapi访问我的api项目,并且可以从http://locahost访问我的Angular项目。现在两者都使用相同的域。

在开始开发工作时启动nginx服务器,然后像往常一样启动api项目和Angular项目。

在全部运行之后,您可以导航到localhost上的应用程序,如果要导航到Api项目中的端点,则可以转到类似http://localhost/myapi/api/values/1的地方。

还要注意,我已经注释掉了这一行: proxy_set_header Connection 'upgrade';在nginx.conf位置,而是使用: proxy_set_header Connection $http_connection;。您需要这样做,以便将数据发送到非GET端点并正常工作。

在使用AntiforgeryToken进行设置时,根据我在此设置中发现的另一件事,需要进行设置,如果在启动文件中设置了这些文件... options.Filters.Add<AutoValidateAntiforgeryTokenAttribute>(); 要么 services.AddScoped<AutoValidateAntiforgeryTokenAttribute>(); 并且还使用[AutoValidateAntiforgeryToken]类级别属性似乎并未启动任何验证。我必须将[ValidateAntiForgeryToken]属性添加到我们要运行防伪验证的方法中。也许有人可以对此发表评论。