Asp POST 不允许网络核心错误 405 方法

Asp net core Error 405 method not allowed on POST

我有一个使用 .NET 5 开发的 asp 网络核心应用程序。

在此应用程序中,有一个控制器 (ACSController) 管理来自身份提供者的响应。 控制器 是以下:

public class ACSController : Controller
{
    private readonly IRequestRepository _requestRepository;
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IIdpRepository _idpRepository;
    private readonly IResponseRepository _responseRepository;

    private readonly AppSessionViewModel _session;

    public ACSController(IRequestRepository requestRepository, IHttpClientFactory httpClientFactory,
        IIdpRepository idpRepository, IResponseRepository responseRepository, AppSessionViewModel session)
    {
        _requestRepository = requestRepository;
        _httpClientFactory = httpClientFactory;
        _idpRepository = idpRepository;
        _responseRepository = responseRepository;

        _session = session;
    }

    [HttpPost]
    public async Task<IActionResult> IndexAsync(IFormCollection form)
    {
        var base64Response = form["SAMLResponse"].ToString();
        var response = SAMLHelper.GetAuthnResponse(base64Response);

        var cachedRequest = _requestRepository.Read();
        var idpMetadata = await SamlHandler.DownloadIdPMetadata(_httpClientFactory,
            _idpRepository.Read().OrganizationUrlMetadata);

        var validationResult = ResponseValidator.ValidateAuthnResponse(response, cachedRequest, idpMetadata);

        if (validationResult.IsSuccess)
        {
            _responseRepository.Write(response);
            _session.Logged = true;
            ViewData["UserInfo"] = CreateUserInfo(response);
            return View();
        }
        else
        {
            ViewData["Message"] = validationResult.Error;
            return View("Error");
        }
    }

    [HttpPost]
    public IActionResult Logout(IFormCollection form)
    {
        var base64Response = form["SAMLResponse"].ToString();
        return View();
    }

    

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }

    #region Utilities

    private Dictionary<string, string> CreateUserInfo(AuthnResponse response)
    {
        if (response == null) throw new ArgumentException(nameof(response));

        var attributes = response.GetAssertion().GetAttributeStatement().Items;

        var userDictionary = new Dictionary<string, string>();

        foreach (var attribute in attributes)
        {
            var attr = (AttributeType)attribute;
            userDictionary.Add(attr.Name, (string)attr.AttributeValue.First());
        }

        return userDictionary;
    }

    #endregion
}

在我的例子中,当 POST 请求调用 acs/index 方法时没有问题。

当我(从另一个控制器)调用注销过程时,我的应用程序正确发送了请求,但是当 IdP 响应我时,我在浏览器上获得了这个响应: https:///acs/logout?SAMLResponse=fVLBSsNAEL0L%2FYeS%2Bya72b … 出现 405 错误。

这是我的 Startup.cs :

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        services.AddSingleton<IRequestRepository, RequestRepository>();
        services.AddSingleton<IIdpRepository, IdpRepository>();
        services.AddSingleton<IResponseRepository, ResponseRepository>();

        services.AddSingleton<AppSessionViewModel>();
        
        services.AddHttpClient();

        services.Configure<Spid>(Configuration.GetSection("Spid"));
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        //app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        //app.UseSession();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

这是我的 launchSettings.json(我使用 SPID_Test 作为网络浏览器):

"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
  "applicationUrl": "http://localhost:15378",
  "sslPort": 0
}

},

"profiles": {
"IIS Express": {
  "commandName": "IISExpress",
  "launchBrowser": true,
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
}

"SPID_Test": {
  "commandName": "Project",
  "launchBrowser": true,
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Production"
  },
  "dotnetRunMessages": "true",
  "applicationUrl": "http://localhost:5000"
}

尝试将[HttpPost]改为[HttpGet],然后将IFormCollection form改为string SAMLResponseModel binding默认从Query字符串参数中获取数据,所以可以通过 default.Here 将 string SAMLResponseSAMLResponse=xxx 绑定是一个演示:

[HttpGet]
        public IActionResult Logout(string SAMLResponse)
        {
            var base64Response = SAMLResponse;
            return View();
        }

结果:

更新:

如果你想解码一个base64字符串,尝试使用:

byte[] data = Convert.FromBase64String(SAMLResponse);
 string decodedString = Encoding.UTF8.GetString(data);