此外,使用现有身份验证对作为 Azure WebApp 托管的 ASP.NET Core MVC 网站进行密码保护

cit*_*nas 6 c# authentication asp.net-core-mvc azure-web-app-service asp.net-core

我有一个具有 ASP.NET Core Identity 的现有 ASP.NET Core MVC 应用程序,其中我使用signInManager.PasswordSignInAsync[Authorize]属性的组合来强制用户登录到网站,具有特定的角色等等。这在本地和 Azure WebApp 中运行良好。

现在,我想将应用程序的预览版本发布到另一个 Azure WebApp。这次,我希望每个访问者在显示网站上的任何内容之前输入另一组凭据。我想我想要类似 .htaccess / BasicAuthenication 的等价物。然而,在用户输入第一组凭据后,他不应该登录,因为他应该需要使用正常的登录程序(就像在可公开访问的实时版本中一样,但它有某些页面需要用户登录)。基本上,我只是想在上面添加另一层密码保护,而不影响当前现有的身份验证

鉴于我希望允许使用预览密码的任何人进行访问,以下解决方案似乎不适用于我的情况:

  • 作为防火墙设置限制对 WebApp 的访问。客户端 IP 不会来自某个特定的 IP 范围,它们将由其 ISP 动态分配。
  • 使用前面带有 Azure AD 的个人用户帐户。这可能是我的后备方案(尽管我不确定如何准确实施),但我不想再需要处理另一组个人用户凭据凭证甚至可以是像预览//预览一样简单的东西。

有没有一种简单的方法,比如在 Startup 类中添加两行代码来实现我想要的第二级密码保护?

Ric*_*y G 4

您可以通过基本身份验证进行第二次身份验证,这很简单,不需要太多代码。您将需要一个中间件,该中间件将在原始身份验证完成后拦截/调用

中间件

public class SecondaryBasicAuthenticationMiddleware : IMiddleware
{
    //CHANGE THIS TO SOMETHING STRONGER SO BRUTE FORCE ATTEMPTS CAN BE AVOIDED
    private const string UserName = "TestUser1";
    private const string Password = "TestPassword1";

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        //Only do the secondary auth if the user is already authenticated
        if (!context.User.Identity.IsAuthenticated)
        {
            string authHeader = context.Request.Headers["Authorization"];
            if (authHeader != null && authHeader.StartsWith("Basic "))
            {
                // Get the encoded username and password
                var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();

                // Decode from Base64 to string
                var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));

                // Split username and password
                var username = decodedUsernamePassword.Split(':', 2)[0];
                var password = decodedUsernamePassword.Split(':', 2)[1];

                // Check if login is correct
                if (IsAuthorized(username, password))
                {                   
                    
                    await next.Invoke(context);
                    return;
                }
            }

            // Return authentication type (causes browser to show login dialog)
            context.Response.Headers["WWW-Authenticate"] = "Basic";

            // Return unauthorized
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        }
        else
        {
            await next.Invoke(context);
        }
    }

    //If you have a db another source you want to check then you can do that here
    private bool IsAuthorized(string username, string password) =>
        UserName == username && Password == password;
}
Run Code Online (Sandbox Code Playgroud)

在启动 -> 配置(确保在现有身份验证和授权之后添加此内容)

    //Enable Swagger and SwaggerUI
    app.UseMiddleware<SecondaryBasicAuthenticationMiddleware>(); //can turn this into an extension if you wish

    app.UseAuthentication();
    app.UseAuthorization();        
Run Code Online (Sandbox Code Playgroud)

在启动 -> 配置服务中注册中间件

services.AddTransient<SecondaryBasicAuthenticationMiddleware>();
Run Code Online (Sandbox Code Playgroud)

chrome 应该弹出一个像这样的基本身份验证对话框

在此输入图像描述