当我对Web API进行POST时,出现401异常

时间:2018-08-23 15:44:27

标签: ajax asp.net-core-webapi

我正在使用开发计算机上的localhost对Web Core API服务器进行Ajax调用。 这是进行呼叫的代码;

<chat-home/>

但是,我收到401未经授权的用户异常。 在我的启动Configure方法中,我按如下所示设置了CORS

addDataToDatabase = function (callback, errorCallback, url, data) {
    $.ajax({
        async: true,
        url: url,
        contentType: "application/json",
        dataType: "text",
        data: data,
        type: "POST",
        xhrFields: { withCredentials: true }
    })
        .done(function (data) {
            callback(data);
        })
        .fail(function (data) {
            errorCallback(data);
        });

在我的appSettings文件中,设置orginUrl:

    var url = Configuration["originUrl"];
    app.UseCors(
        options => options.WithOrigins(url).AllowAnyHeader().AllowAnyMethod().AllowCredentials()
    ); 

所有这些都适用于GET类型的调用,但不适用于POST。 我需要解决什么?

编辑-根据要求,这是完整的启动代码;

"originUrl": "http://localhost:12345"

这是引发401异常的POST方法;

using Microsoft.AspNetCore.Mvc.ApplicationParts;

namespace Properties.API
{
    using Domain;
    using Domain.Interfaces;
    using Domain.Repo;
    using EF6;
    using Helper;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using NLog;
    using NLog.Config;
    using NLog.Extensions.Logging;
    using NLog.Web;
    using Sir.EF6;
    using Sir.EF6.Interfaces;
    using Sir.EF6.Repo;

    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appSettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appSettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables();

            Configuration = builder.Build();
        }

        public static IConfigurationRoot Configuration;

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            var manager = new ApplicationPartManager();
            manager.ApplicationParts.Add(new AssemblyPart(typeof(Startup).Assembly));
            services.AddSingleton(manager);
            services.AddCors();
            services.AddMvcCore().AddJsonFormatters();
            services.Configure<IISOptions>(options => new IISOptions
            {
                AutomaticAuthentication = true,
                ForwardClientCertificate = false,
                ForwardWindowsAuthentication = false
            });

            var connectionStringMSurveyV2 = Configuration.GetConnectionString("MSurveyV2Db");
            services.AddScoped<MSurveyV2Db>(_ => new MSurveyV2Db(connectionStringMSurveyV2));
            var connectionStringSir = Configuration.GetConnectionString("SirDb");
            services.AddScoped<SirDb>(_ => new SirDb(connectionStringSir));
            services.AddScoped<IPropertiesRepo, PropertiesRepo>();
            services.AddScoped<ISirUoW, SirUoW>();
            services.AddScoped<IPropertyUoW, PropertyUoW>();
            services.AddScoped<Services.IMailService, Services.MailService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
            loggerFactory.AddDebug();
            loggerFactory.AddNLog();
            LogManager.Configuration = new XmlLoggingConfiguration(@"nlog.config");
            var connectionString = Configuration.GetConnectionString("SirNLogDb");
            LogManager.Configuration.Variables["SirNLogDb"] = connectionString;
            app.AddNLogWeb();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler();
            }

            var url = Configuration["originUrl"];
            app.UseCors(
                options => options.WithOrigins(url).AllowAnyHeader().AllowAnyMethod().AllowCredentials()
            );

            app.UseMvc();
            AutomapperInit.Set();
            var logger = LogManager.GetCurrentClassLogger();
            logger.Info("Started Properties Web API");
            logger.Info($"Origin url = {url}");
        }
    }
}

这是一个可以正常工作的GET方法

[HttpPost("add")]
public async Task<IActionResult> Add([FromBody] InspectionVisitInputDto inspectionVisitDto)
{
    this.NLogger.Info("api/inspectionVisit/add".ToPrefix());
    if (inspectionVisitDto == null)
    {
        NLogger.Error("No data sent");
        return BadRequest(ModelState);
    }

    if (inspectionVisitDto.InspectionId < 1)
    {
        NLogger.Error($"Invalid InspectionId < 1 (actual value is {inspectionVisitDto.InspectionId}");
        return BadRequest(ModelState);
    }

    var inspectionVisit = Mapper.Map<InspectionVisit>(inspectionVisitDto);
    var dateOfVisit = inspectionVisit.DateOfVisit.Date;
    try
    {
        var existingInspectionVisit = this.SirUoW.InspectionVisit.GetItem(
            x => x.InspectionId == inspectionVisit.InspectionId &&
                 DbFunctions.TruncateTime(x.DateOfVisit) == dateOfVisit &&
                 x.ContractSubcontractorId == inspectionVisit.ContractSubcontractorId &&
                 x.SelectedInspectorUsername == inspectionVisit.SelectedInspectorUsername &&
                 x.WorkPhaseId == inspectionVisit.WorkPhaseId);
        if (existingInspectionVisit?.InspectionVisitId > 0)
        {
            NLogger.Info($"Inspection Visit Id = {existingInspectionVisit.InspectionVisitId} already exists.");
            return Ok(existingInspectionVisit.InspectionVisitId);
        }
    }
    catch (Exception e)
    {
        var message = "Cannot get inspection visit";
        await ReportException(e, message);
        var status = OperationStatus.CreateFromException(message, e);
        return BadRequest(status);
    }

    NLogger.Info("Add New Inspection Visit");
    try
    {
        this.SirUoW.InspectionVisit.Add(inspectionVisit);
        await SirUoW.LoggedInSaveChangesAsync(this.LoggedInUser);
        NLogger.Info("New Inspection Visit Saved, id = " + inspectionVisit.InspectionVisitId);

        if (inspectionVisit.ContractSubcontractorId != null)
        {
            await SaveContractSubcontractorIdForInspection(inspectionVisitDto);
        }

        return Ok(inspectionVisit.InspectionVisitId);
    }
    catch (Exception e)
    {
        var message = "Cannot save " + inspectionVisitDto;
        await ReportException(e, message);
        var status = OperationStatus.CreateFromException(message, e);
        return BadRequest(status);
    }
}

1 个答案:

答案 0 :(得分:0)

您的方案正在组合 IIS Windows Authenticaiton CORS ,因为预检请求选项将不包含任何安全标头,它将出现错误 401

请尝试以下解决方法:

  1. anonymousAuthentication中启用appsettings.json

    {
      "iisSettings": {
      "windowsAuthentication": true,
     "anonymousAuthentication": true
     }
    }
    
  2. 要启用身份验证,请尝试Filter禁用匿名访问。

      services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
        });