Windows身份验证-特殊用户需要其他密码

nia*_*iao 12 c# windows-authentication asp.net-core

我正在开发一个Intranet asp.net核心Web API应用程序。身份验证的要求是:

  • REQ1-当试图访问该网站的用户不在Active Directory的特殊组中(让其命名为“ commonUsers”)时,它根本没有被授权
  • REQ2-当尝试访问该网站的用户位于Active Directory的组“ commonUsers”中时,将被授权并返回Web资源
  • REQ3-当试图访问该网站的用户位于Active Directory的“ superUser”组中时,需要再次提示其输入域密码(因为它试图访问一些非常受限的资源)

现在,我到目前为止:

  • 我的服务使用http.sys服务器托管,以支持Windows身份验证。
  • 我正在使用Claims Middlewere来检查用户的Active Directory组,让我们说这样的话:

    public class ClaimsTransformer : IClaimsTransformation {
    private readonly IAuthorizationService _authorizationService;
    public ClaimsTransformer(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }
    
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        _authorizationService.Authorize(principal as  IHmiClaimsPrincipal);
        return Task.FromResult(principal);
    }}
    
    Run Code Online (Sandbox Code Playgroud)
  • 我还在服务配置中指定了特殊策略,例如:

    services.AddAuthorization(options =>
        {
            options.AddPolicy(“ TestPolicy”,策略=> 
                                       policy.RequireClaim(ClaimTypes.Role,“ TestUser”));
            options.AddPolicy(“ TestPolicy2”,策略=> 
                                       policy.RequireClaim(ClaimTypes.Role,“ SuperUser”));
        });
  • 我将 [Authorize]属性与特定策略结合使用,以便基于策略限制对特定资源的访问

现在的问题是,我应该如何满足REQ3?

Joh*_*ohn 0

我猜您正在尝试为 实施两步身份验证some of your resource
\n为此,您必须使用多个authentication schemeand Authorize policies,\n但这很困难,因为 Windows 身份验证不可控。我们需要使用一些技巧来知道这是您的第二次登录。

\n\n

验证

\n\n
    \n
  1. 默认身份验证方案:Windows它是对 Windows 用户进行身份验证的基本方案。
  2. \n
  3. 第二Cookies基地认证方案:SuperUserTwoStep。我们需要它来转到我们的自定义登录逻辑。
  4. \n
\n\n

授权

\n\n
    \n
  1. 对于指定的方案Authorize policies
  2. \n
  3. 用于登录方案的登录页面SuperUserTwoStep
  4. \n
\n\n
//startup\n            services.AddAuthentication(HttpSysDefaults.AuthenticationScheme)\n                .AddCookie("SuperUserTwoStep",op=>op.LoginPath = "/account/superuser2steplogin");\n\n            services.AddAuthorization(op =>\n            {\n                op.AddPolicy("SuperUser", b => b.AddAuthenticationSchemes("SuperUserTwoStep")\n                    .RequireAuthenticatedUser()\n                    .RequireClaim(ClaimTypes.Role, "SuperUser"));\n            });\n\n
Run Code Online (Sandbox Code Playgroud)\n\n
// login \n        public static IDictionary<string, string> States { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n\n        [Route("/account/superuser2steplogin")]\n        public async Task<IActionResult> LoginTwoStepConfirm(string returnUrl, [FromServices]IAuthorizationService authorizationService,\n            [FromServices]IAuthorizationPolicyProvider policyProvider)\n        {\n\n            var winresult = await HttpContext.AuthenticateAsync(IISDefaults.AuthenticationScheme);\n            if (winresult.Succeeded)\n            {\n                if (States.TryGetValue(winresult.Principal.Identity.Name, out _))\n                {\n                    States.Remove(winresult.Principal.Identity.Name);\n                    var principal = new System.Security.Claims.ClaimsPrincipal(new System.Security.Claims.ClaimsIdentity(winresult.Principal.Claims,"twostepcookie"));\n                    await HttpContext.SignInAsync("SuperUserTwoStep", principal);\n                    return Redirect(returnUrl);\n                }\n                else\n                {\n                    States[winresult.Principal.Identity.Name] = "1";\n                    return Challenge(IISDefaults.AuthenticationScheme);\n                }\n            }\n\n            else\n            {\n                return Challenge(IISDefaults.AuthenticationScheme);\n            }\n        }\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n        [Authorize("SuperUser")]\n        public IActionResult YourSecurePage()\n        {\n            return Content("hello world");\n        }\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

最困难的是跟踪这是第二次登录,我尝试使用 cookie ,但它不起作用,所以我创建了一个来static IDitionary<string,string>跟踪 \xef\xbc\x8c也许使用分布式缓存更好

\n