如何在.NetCore API中验证从一个应用程序发布到另一应用程序上的AntiForgeryToken? [英] How to validate AntiForgeryToken issued from one Application on different Application in .NetCore API?

查看:91
本文介绍了如何在.NetCore API中验证从一个应用程序发布到另一应用程序上的AntiForgeryToken?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个应用程序,ASP.NET Core Web APP(应用程序1)和.NET CORE API(应用程序2).我在(app 1)中发布了一个AntiForgeryToken,并将其以隐藏字段的形式返回(实际上.netcore是自动生成的).现在,当用户提交表单时,数据转到(app 2)并使用CORS,我能够将(app 1)发行的AntiForgeryToken的cookie发送到(app 2),这样我就可以对其进行验证并在(app 2)上进行验证添加了validateAntiFOrgeryToken属性,以便我可以对其进行验证.以下是我在chrome dev工具的响应"选项卡上收到的错误.

I have two Apps, ASP.NET Core Web APP ( app 1 ) and .NET CORE API ( app 2 ). I issue an AntiForgeryToken in the ( app 1 ) and return it in form as hidden field ( actually .netcore makes it automatically ). now when the user submit the form the data goes to ( app 2 ) and using CORS I was able to send the cookie of AntiForgeryToken issued by ( app 1 ) to ( app 2 ) so i can validate it and on ( app 2 ) I added the validateAntiFOrgeryToken Attribute so that I can validate it. and below is the error I receive on chrome dev tools response tab.

我尝试了所有方法并进行了所有搜索,但是此特定错误找不到答案.

I tried everything and searched all SO but this specific error cant find an answer to it.

System.InvalidOperationException: No service for type 'Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter' has been registered.
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute.CreateInstance(IServiceProvider serviceProvider)
   at Microsoft.AspNetCore.Mvc.Filters.DefaultFilterProvider.ProvideFilter(FilterProviderContext context, FilterItem filterItem)
   at Microsoft.AspNetCore.Mvc.Filters.DefaultFilterProvider.OnProvidersExecuting(FilterProviderContext context)
   at Microsoft.AspNetCore.Mvc.Filters.FilterFactory.CreateUncachedFiltersCore(IFilterProvider[] filterProviders, ActionContext actionContext, List`1 filterItems)
   at Microsoft.AspNetCore.Mvc.Filters.FilterFactory.GetAllFilters(IFilterProvider[] filterProviders, ActionContext actionContext)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerCache.GetCachedResult(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerProvider.OnProvidersExecuting(ActionInvokerProviderContext context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionInvokerFactory.CreateInvoker(ActionContext actionContext)
   at Microsoft.AspNetCore.Mvc.Routing.ActionEndpointFactory.<>c__DisplayClass7_0.<CreateRequestDelegate>b__0(HttpContext context)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: close
Content-Length: 98
Content-Type: application/json
Cookie: .AspNetCore.Antiforgery.P09gDl3q4JU=CfDJ8MTlw3i2dFxEnHbgYLq-NTBvWTMlXSM5JV9sH03i3b4ulUq0JlSns86jxwas797wsxz9mOS2JDlK6nhntJGc80bpNNwUyUnOQou-iTEwsykSBE7-yfc05pjknlLMNciWmrLzxHaJ-kpG8Tjnqo7jxbc
Host: localhost:44375
Pragma: no-cache
Referer: https://localhost:44389/account/signup
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
origin: https://localhost:44389
x-xsrf-token: CfDJ8MTlw3i2dFxEnHbgYLq-NTB8DUVF73lPTj3HAOL2bhD-sIDv2N4Fs0JowHt6W-WB5oQltt8ELtCH03XYq2QAxz96SYseDR-pZ6XMXAXRE8mpGUatGKtWp_yNohpbYt2ZQD25NzYqYdw-fCi3hsdQf1g
sec-fetch-site: same-site
sec-fetch-mode: cors

这是应用1的代码:

(查看)

<div class="form-container">

    <div class="form-inputs">
        <form id="signup-form" method="post">
            <!-- Input and Submit elements -->
            @Html.AntiForgeryToken()
            <input type="email" name="email" data-send="true" placeholder="Email Address" />
            <span class="error"></span>
            <input type="password" name="password" data-send="true" placeholder="Password" data-validate="true" data-val-min="8" data-val-max="20" data-val-length-error="Password must be between 8 and 20 characters" data-val-empty-error="Password is required" />
            <span class="error"></span>
            <input type="password" name="confirmpassword" data-send="true" data-validate="true" data-val-compare="password" data-val-empty-error="Confirm Password is required" data-val-compare-error="Password doesn't match" placeholder="Confirm Password" />
            <span class="error"></span>
            <input type="text" name="username" placeholder="Username" data-send="true" data-validate="true" data-val-min="3" data-val-max="10" data-val-length-error="Username must be between 3 and 10 characters" data-val-empty-error="Username is required" />
            <span class="error"></span>
            <div class="button-holder">
                <button id="signup" class="action"><span id="loader"><i class="fas fa-spinner"></i></span><span id="button-text">signup</span></button>
            </div>
            <div class="terms-holder">
                <p>By Creating an account you agree to our <span><a href="#">Terms of Use</a></span> and <span><a href="#">Privacy Policy</a></span></p>
            </div>
        </form>



    </div>
</div>

,这里是应用2的代码:

and here the code for app 2 :

(startup.cs)

(startup.cs)

using System.Text;
using Authentication.Models;
using Authentication.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;

namespace API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        readonly string OnlyOrigin = "OnlyOrigin";

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {


            services.AddCors(options => 
            {
                options.AddDefaultPolicy(
                builder => builder.WithOrigins("https://localhost:44389")
                    .AllowAnyMethod()
                    .AllowCredentials()
                    .WithHeaders("content-type","X-XSRF-TOKEN")
                    );

            });
            services.AddAntiforgery(options =>
            {
                // Set Cookie properties using CookieBuilder properties†.
                options.HeaderName = "X-XSRF-TOKEN";
                options.SuppressXFrameOptionsHeader = false;
            });
            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });
            services.AddControllers();
            services.AddScoped<IAccount, AccountManager>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseCors();
            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

(控制器):

using API.Models;
using Authentication.Models;
using Authentication.Services;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace API.Controllers
{
    [Route("api/authentication")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        private readonly IAccount accountService;
        private readonly HttpContext Context;

        public AuthenticationController(IAccount accountService, IHttpContextAccessor contextAccessor)
        {
            this.accountService = accountService;
            this.Context = contextAccessor.HttpContext;
        }

        [HttpPost]
        [Consumes("application/json")]
        [Produces("application/json")]
        [Route("account/signup")]
        //[EnableCors("Only Origin")]
        [ValidateAntiForgeryToken]
        public string Signup([FromBody] Account account)

        {
            if(!ModelState.IsValid)
            {
                return "not valid";
            }
            return accountService.CreateAccount(account);

        }

        [HttpPost]
        [Consumes("application/json")]
        [Produces("application/json")]
        [Route("account/signin")]
        [ValidateAntiForgeryToken]
        public IActionResult Signin(LoginViewModel loginViewModel)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(new Result
                {
                    Type = "Error",
                    Return = "not valid"
                });
            }
            Result result = accountService.Login(loginViewModel.Email, loginViewModel.Password);
            return Ok(result);
        }



    }
}

(JQuery):

this.send = function () {
        alert(csrf);
        $.ajax({
            url: "https://localhost:44375/api/authentication/account/signup",
            headers: {
                'Content-Type': 'application/json',
                'X-XSRF-TOKEN': csrf
            },
            xhrFields: {
                withCredentials: true
            },
            method: 'POST',
            dataType: 'json',
            data: getDataToSend(),
            success: function (data) {
                console.log('succes: ' + data);
            }
        });
    }

(请求标头):

:authority: localhost:44375
:method: POST
:path: /api/authentication/account/signup
:scheme: https
accept: application/json, text/javascript, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: en-GB,en-US;q=0.9,en;q=0.8
cache-control: no-cache
content-length: 98
content-type: application/json
cookie: .AspNetCore.Antiforgery.P09gDl3q4JU=CfDJ8MTlw3i2dFxEnHbgYLq-NTBvWTMlXSM5JV9sH03i3b4ulUq0JlSns86jxwas797wsxz9mOS2JDlK6nhntJGc80bpNNwUyUnOQou-iTEwsykSBE7-yfc05pjknlLMNciWmrLzxHaJ-kpG8Tjnqo7jxbc
origin: https://localhost:44389
pragma: no-cache
referer: https://localhost:44389/account/signup
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
x-xsrf-token: CfDJ8MTlw3i2dFxEnHbgYLq-NTB8DUVF73lPTj3HAOL2bhD-sIDv2N4Fs0JowHt6W-WB5oQltt8ELtCH03XYq2QAxz96SYseDR-pZ6XMXAXRE8mpGUatGKtWp_yNohpbYt2ZQD25NzYqYdw-fCi3hsdQf1g

推荐答案

如果您不希望发生该异常,则必须使用

If you don't want that exception to occur you have to use

services.AddControllersWithViews()

代替

services.AddControllers()

这篇关于如何在.NetCore API中验证从一个应用程序发布到另一应用程序上的AntiForgeryToken?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆