使用Windows Auth验证用户身份,然后在ASPNET Core 2.1中生成JWT

时间:2019-08-29 13:19:29

标签: asp.net-core jwt asp.net-core-webapi windows-authentication

我有一个ASP.NET Core 2.1 WebApi,在其中实现了JWT身份验证。用户调用api/authentication/authenticate,在消息正文中传递其用户名/密码,并返回JWT作为回报,然后他们将其用于访问服务。

我还需要API接受Windows身份验证-用户将调用api/authentication/windows且不传递任何用户信息,该服务将检查他们是否在web.config文件中列出的授权用户列表中(如果我在IIS中托管。如果是这样,则返回JWT令牌,用户可以使用该令牌访问服务。

当前我正在考虑...

  1. api/authentication/windows方法将从请求中获取用户名
  2. 根据授权用户列表检查用户名。如果它们在上面,则返回令牌。如果不是,请转到(3)
  3. 检查授权用户列表中的任何组。如果它们是成员,则返回令牌。如果不是,则返回401未经授权错误

这是解决此问题的正确方法吗?

此处非常相似(未回答)的问题:Generate JWT token on successful authentication with Windows Authentication

2 个答案:

答案 0 :(得分:1)

如果要同时启用JWT和AD身份验证,则我仍然需要针对Web api中的Active Directory验证用户的凭据(用户名/密码):

https://www.brechtbaekelandt.net/blog/post/authenticating-against-active-directory-with-aspnet-core-2-and-managing-users

仅传递用户名无效,因为Web api中没有经过身份验证的用户上下文。

验证用户凭证后,您可以照常生成jwt令牌,例如,如果使用HS256:

private string BuildToken()
{
    var claims = new[] {
        new Claim(JwtRegisteredClaimNames.NameId,"name1"),
        new Claim(JwtRegisteredClaimNames.Sub,"name1"),
        new Claim("customer","customer1"),
        new Claim(JwtRegisteredClaimNames.Email,"wuxiyuan@sina,com"),
        new Claim("role","user"),
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Youkey"));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken("name1",
        "name1",
    claims,
    expires: DateTime.Now.AddDays(1),
    signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

答案 1 :(得分:0)

   <configuration>
     <system.webServer>
       <security>
         <authentication>
           <anonymousAuthentication enabled="true" />
           <windowsAuthentication enabled="true" />
         </authentication>
       </security>
     </system.webServer>
   </configuration>
   "iisSettings": {
     "windowsAuthentication": true,
   }
  • 使匿名身份验证保持激活状态:<anonymousAuthentication enabled=" true " />。为了使JWT身份验证对于路由api/authentication/authenticate

  • 正常工作,这是必要的
  • 请确保未停用forwardWindowsAuthToken中aspNetCore元素的属性web.configforwardWindowsAuthToken="true"或由于默认值( true

  • IISIntegration添加到webHostBuilder,除非您使用默认生成器:WebHost.CreateDefaultBuilder(args)-UseIISIntegration在此扩展方法内称为隐式。

  • POST方法添加Authorize属性,该属性将与路由api/authentication/windows

  • 映射
  • 测试身份验证(发送Windows凭据):

    var handler = new System.Net.Http.HttpClientHandler()
    {
        Credentials = System.Net.CredentialCache.DefaultCredentials
    };

    var httpClient = new System.Net.Http.HttpClient(handler)
    {
        BaseAddress = new Uri("http://localhost")
    };

    var response = await httpClient.PostAsync("api/authentication/windows", null);

或使用XMLHttpRequest对象:

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://localhost/api/authentication/windows', true);
    xhr.withCredentials = true;
    xhr.send();
  • 在控制器中获取用户名:
    var username = HttpContext.User.FindFirst(System.Security.Claims.ClaimTypes.Name)?.Value;
  • 例如使用jose-jwt生成JWT令牌:
 var claims = new Dictionary<string, object>
 {
     ["jti"] = Guid.NewGuid(),
     ["sub"] = username,
     ["exp"] = DateTimeOffset.UtcNow.AddMinutes(100).ToUnixTimeSeconds()
 };

 var secretKey = new byte[] { 164, 60, 194, 0, 161 };

 var headers = new Dictionary<string, object>
 {
     ["alg"] = "HS512",
     ["typ"] = "JWT"
 };

 var token = JWT.Encode(claims, secretKey, JwsAlgorithm.HS512, headers);