我的自定义授权属性(用于基本身份验证)有什么问题?

发布于 2025-01-12 12:33:32 字数 2806 浏览 4 评论 0原文

我有一个 .NET 6.0 Web 应用程序,它使用基于 Cookie 的用户身份验证。

今天我想添加一个具有非常简单的基本身份验证机制的 API 控制器。

这是我的控制器:

public class DemaController : Controller
{
    [HttpGet("test")]
    [BasicAuthentication(username: "test", password: "abc")]
    public bool Test()
    {
        return true;
    }
}

这是我的超级简单的基本身份验证属性:

public class BasicAuthenticationAttribute : Attribute, IAuthorizationFilter
{
    private readonly string _username;
    private readonly string _password;

    public BasicAuthenticationAttribute(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        try
        {
            var authorizationHeader = context.HttpContext.Request.Headers["Authorization"];
            (string username, string password) = this.GetUsernameAndPassword(authorizationHeader: authorizationHeader);

            if (username != null && password != null)
            {
                if (username == _username && password == _password)
                    return; // Grant access
            }
        }
        catch (FormatException)
        {
        }

        context.Result = new UnauthorizedResult();
    }

    static System.Text.Encoding ISO_8859_1_ENCODING = System.Text.Encoding.GetEncoding("ISO-8859-1");
    private (string, string) GetUsernameAndPassword(string authorizationHeader)
    {
        if (authorizationHeader == null || !authorizationHeader.Contains("Basic "))
            return (null, null);

        string encodedUsernamePassword = authorizationHeader.Substring("Basic ".Length).Trim();
        string usernamePassword = ISO_8859_1_ENCODING.GetString(Convert.FromBase64String(encodedUsernamePassword));

        string username = usernamePassword.Split(':')[0];
        string password = usernamePassword.Split(':')[1];

        return (username, password);
    }
}

当我在本地计算机(Visual Studio 2022 + IIS Express)上运行应用程序并使用 Postman 访问 Api 时,一切正常。正如预期的那样,响应是“true”。

这就是我提供邮递员的方式:

  • GET https://localhost:44360/test
  • 授权类型:基本身份验证
  • 用户名:test
  • 密码:abc

所以我的自定义 BasicAuthenticationAttribute 似乎有效。我可以设置断点(正在被击中),并且对 Postman 凭据的任何更改都会返回 Http-401 错误。

到目前为止,一切都很好。

现在我将应用程序发布到我的生产服务器 (IIS)。在 Postman 中,我用我的真实生产域替换了“localhost:44360”。

我的问题:将请求发送到我的生产服务器会返回 401(以及整个 ASP.NET Core 默认错误页面)。

我更进一步,在我的服务器上设置了 MS Visual Studio 远程调试器。然后我在自定义 BasicAuthenticationAttribute 中设置了一个断点。断点永远不会被命中。换句话说:401 不是来自我的属性内部。看来我的 BasicAuthenticationAttribute 在我的服务器上根本没有被触及(但在我的开发机器上肯定会被触及,如前所述)。

让我猜猜:我需要在 Startup.cs 中添加或更改某些内容?

就其价值而言:我知道基本身份验证并不真正安全。但对于我的需求来说,这完全没问题。无论如何,我想绕过复杂的策略、OAuth 等。

有人知道我需要做什么吗?

I have a .NET 6.0 web application which is using Cookie based authentication for users.

Today I wanted to add an API controller with a really simple BASIC AUTHENTICATION mechanism.

Here is my controller:

public class DemaController : Controller
{
    [HttpGet("test")]
    [BasicAuthentication(username: "test", password: "abc")]
    public bool Test()
    {
        return true;
    }
}

and here is my super simple Basic Authentication attribute:

public class BasicAuthenticationAttribute : Attribute, IAuthorizationFilter
{
    private readonly string _username;
    private readonly string _password;

    public BasicAuthenticationAttribute(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        try
        {
            var authorizationHeader = context.HttpContext.Request.Headers["Authorization"];
            (string username, string password) = this.GetUsernameAndPassword(authorizationHeader: authorizationHeader);

            if (username != null && password != null)
            {
                if (username == _username && password == _password)
                    return; // Grant access
            }
        }
        catch (FormatException)
        {
        }

        context.Result = new UnauthorizedResult();
    }

    static System.Text.Encoding ISO_8859_1_ENCODING = System.Text.Encoding.GetEncoding("ISO-8859-1");
    private (string, string) GetUsernameAndPassword(string authorizationHeader)
    {
        if (authorizationHeader == null || !authorizationHeader.Contains("Basic "))
            return (null, null);

        string encodedUsernamePassword = authorizationHeader.Substring("Basic ".Length).Trim();
        string usernamePassword = ISO_8859_1_ENCODING.GetString(Convert.FromBase64String(encodedUsernamePassword));

        string username = usernamePassword.Split(':')[0];
        string password = usernamePassword.Split(':')[1];

        return (username, password);
    }
}

When I run the application on my local machine (Visual Studio 2022 + IIS Express) and use Postman to access the Api everything works just fine. The response is "true" as expected.

This is how I feed Postman:

  • GET https://localhost:44360/test
  • Authorization type: Basic Auth
  • Username: test
  • Password: abc

So my custom BasicAuthenticationAttribute seems to work. I can set break points (which are being hit) and any change to the Postman credentials returns an Http-401 error.

So far so good.

Now I published my application to my production server (IIS). In Postman, I replaced "localhost:44360" by my real production domain.

My problem: Sending the request to my production server returns a 401 (and a whole ASP.NET Core default error page).

I went a little further and setup the MS Visual Studio Remote Debugger on my server. Then I set a breakpoint inside my custom BasicAuthenticationAttribute. The breakpoint is never hit. In other words: the 401 does not come from inside my attribute. It seems like my BasicAuthenticationAttribute is not touched at all on my server (but it is touched for sure on my development machine as stated before).

Let me guess: I need to add or change something in my Startup.cs?

For what it's worth: I am aware that Basic Authentication is not really safe. But for my needs it's totally fine. In any case I want to get around complex Policies, OAuth etc.

Does anybody have an idea what I need to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

动听の歌 2025-01-19 12:33:32

现在我将应用程序发布到我的生产服务器 (IIS)。在 Postman 中,我将“localhost:44360”替换为我的真实生产域。

我的问题:将请求发送到我的生产服务器会返回 401(以及整个 ASP.NET Core 默认错误页面)。

尝试检查 IIS 是否有基本身份验证或 Windows 身份验证。如果有,请在 IIS 中禁用它们,然后重试。

Now I published my application to my production server (IIS). In Postman, I replaced "localhost:44360" by my real production domain.

My problem: Sending the request to my production server returns a 401 (and a whole ASP.NET Core default error page).

Try to check if IIS had Basic authentication or Windows authentication.If so,disable them in IIS and try again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文