【问题标题】:Asp net core Error 405 method not allowed on POSTPOST 上不允许使用 Asp net core 错误 405 方法
【发布时间】:2021-11-03 12:15:31
【问题描述】:

我有一个用 .NET 5 开发的 asp net core 应用程序。

在此应用程序中,有一个控制器 (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"
}

【问题讨论】:

  • 浏览器最有可能发出 GET 请求,而控制器并非旨在处理该请求
  • 使用 [HttpGet] 我的控制器被触发,但 SAMLResponse 似乎不是 base64 字符串并且我的应用程序崩溃了。

标签: asp.net-core http-post saml


【解决方案1】:

尝试将[HttpPost]改为[HttpGet],然后将IFormCollection form改为string SAMLResponseModel binding默认从查询字符串参数中获取数据,所以默认可以绑定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);

【讨论】:

  • 它似乎有效。现在还有另一个问题,因为字符串SAMLResponse 不是base64 字符串,但我需要一个base64 字符串。有什么想法吗?
  • 数据取决于你在url中传递的内容(SAMLResponse=xxx)?如果你在url中传递base64字符串,SAMLResponse将是base64字符串。
  • 我的问题是SAMLResponse 是由身份提供者发送的,我需要“解码”它。字符串不是我编的。
  • 我已经更新了关于如何解码 base64 字符串的答案。
  • 现在我得到以下异常:“输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非法字符。”
猜你喜欢
  • 2019-07-01
  • 2012-08-24
  • 2018-02-16
  • 2019-07-05
  • 2013-12-05
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 2017-10-16
相关资源
最近更新 更多