User.Identity.Name 在 Asp.NET Core 2.0 API 控制器中为空
User.Identity.Name is empty in Asp.NET Core 2.0 API Controller
我是 ASP.NET 核心本身的新手。但是,我正在 ASP.NET Core 2.0 中创建 WebAPIs。我已经配置了基于 JWT Bearer Token 的身份验证。下面是我的控制器,其中 return 令牌。
[AllowAnonymous]
[Route("api/[controller]")]
public class TokenController : Controller
{
private readonly UserManager<UserEntity> userManager;
private readonly SignInManager<UserEntity> signInManager;
public TokenController(UserManager<UserEntity> userManager, SignInManager<UserEntity> signInManager)
{
this.userManager = userManager;
this.signInManager = signInManager;
}
// GET: api/values
[HttpGet]
public async Task<IActionResult> Get(string username, string password, string grant_type)
{
{
var user = await userManager.FindByEmailAsync(username);
if (user != null)
{
var result =await signInManager.CheckPasswordSignInAsync(user, password, false);
if (result.Succeeded)
{
var claims = new[]
{
new Claim( JwtRegisteredClaimNames.Sub, username),
new Claim( JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim( JwtRegisteredClaimNames.GivenName, "SomeUserID")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secretesecretesecretesecretesecretesecrete"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken( issuer: "test",
audience: "test",
claims: claims,
expires: DateTime.Now.AddDays(15),
signingCredentials: creds);
return Ok(new { access_token = new JwtSecurityTokenHandler().WriteToken(token), expires_on=DateTime.Now.AddDays(15) });
}
}
}
return BadRequest("Could not create token");
}
}
但是当调用用 [Authorize] 属性修饰的 ValuesController API 时。我得到 User.Identity.Name 是空的。我没有得到有关用户的任何信息。我不确定,我的令牌控制器是否正确编写。只要它保护我的 ValuesController,我认为它就是正确的。但是,我可能会遗漏一些东西。请帮忙。
Note: I am developing using Visual Studio 2017 with Mac Community
addition
是的,您需要为翻译成 user.identity.name:
的唯一名称指定声明
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
我在使用 ASP.Net Core 2 时也遇到了这个问题,我真的很惊讶没有人发现这个问题的其他原因。
当我的 webapp 部署到 IIS 时,“User.Identity.Name
”总是 returns 空。 IIS 站点已禁用匿名访问,并且已启用 windows 身份验证。
但是。
没想到我的ASP.Net Core 2有一个“launchSettings.json
”文件,悄悄地藏在Properties
文件夹下,里面还有一些iisSettings,奇怪的是,这里的“windowsAuthentication
”默认设置为 false。
将“windowsAuthentication
”更改为 true,将“anonymousAuthentication
”更改为 false 解决了我的问题。
这样做之后,“User.Identity.Name
”终于包含了正确的用户名。
但是这个设置到底是什么?为什么 this 优先于我们在 IIS 管理器中设置的实际设置?!
使用 "DefaultIdentity"(个人用户帐户)也有这个问题(Core 3.1)。
User.Identity.Name 为空,User.Identity.IsAuthenticated = 真。
通过使用 httpContextAccessor,您可以获得 userId,并使用该 id 找到用户和 UserName。
在你的控制器中添加
using System.Security.Claims;
...
private readonly IHttpContextAccessor _httpContextAccessor;
public MyController(MyContext context, IHttpContextAccessor httpContextAccessor)
{
_context = context;
_httpContextAccessor = httpContextAccessor;
}
// Any method username needed
[HttpGet("{id}")]
public async Task<ActionResult<MyInfo>> GetMyInfo(int id)
{
var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
var user = _context.AspNetUsers.Find(userId);
var userName = user.UserName;
...
}
在 Startup.cs 中添加以下行:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
对于 Azure OAuth v2,使用 preferred_username 而不是 unique_name (see this and this)。
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
serviceCollection.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.RoleClaimType = "roles";
options.TokenValidationParameters.NameClaimType = "preferred_username";
//options.TokenValidationParameters.NameClaimType = "email"; // or if you want to use user's email for User.Identity.Name
//below lines of code can be removed. just there if you want some code to be executed right after user is validated.
options.Events.OnTokenValidated = async context =>
{
var personFirstName = context.Principal.FindFirstValue("given_name") ?? string.Empty;
var personLastName = context.Principal.FindFirstValue("family_name") ?? string.Empty;
var personEmail = context.Principal.FindFirstValue("email")?.ToLower();
var personName = context.Principal.Identity.Name;
};
});
然后在您的控制器中,您将从 User.Identity.Name
获取用户名
我是 ASP.NET 核心本身的新手。但是,我正在 ASP.NET Core 2.0 中创建 WebAPIs。我已经配置了基于 JWT Bearer Token 的身份验证。下面是我的控制器,其中 return 令牌。
[AllowAnonymous]
[Route("api/[controller]")]
public class TokenController : Controller
{
private readonly UserManager<UserEntity> userManager;
private readonly SignInManager<UserEntity> signInManager;
public TokenController(UserManager<UserEntity> userManager, SignInManager<UserEntity> signInManager)
{
this.userManager = userManager;
this.signInManager = signInManager;
}
// GET: api/values
[HttpGet]
public async Task<IActionResult> Get(string username, string password, string grant_type)
{
{
var user = await userManager.FindByEmailAsync(username);
if (user != null)
{
var result =await signInManager.CheckPasswordSignInAsync(user, password, false);
if (result.Succeeded)
{
var claims = new[]
{
new Claim( JwtRegisteredClaimNames.Sub, username),
new Claim( JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim( JwtRegisteredClaimNames.GivenName, "SomeUserID")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secretesecretesecretesecretesecretesecrete"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken( issuer: "test",
audience: "test",
claims: claims,
expires: DateTime.Now.AddDays(15),
signingCredentials: creds);
return Ok(new { access_token = new JwtSecurityTokenHandler().WriteToken(token), expires_on=DateTime.Now.AddDays(15) });
}
}
}
return BadRequest("Could not create token");
}
}
但是当调用用 [Authorize] 属性修饰的 ValuesController API 时。我得到 User.Identity.Name 是空的。我没有得到有关用户的任何信息。我不确定,我的令牌控制器是否正确编写。只要它保护我的 ValuesController,我认为它就是正确的。但是,我可能会遗漏一些东西。请帮忙。
Note: I am developing using Visual Studio 2017 with Mac Community addition
是的,您需要为翻译成 user.identity.name:
的唯一名称指定声明new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
我在使用 ASP.Net Core 2 时也遇到了这个问题,我真的很惊讶没有人发现这个问题的其他原因。
当我的 webapp 部署到 IIS 时,“User.Identity.Name
”总是 returns 空。 IIS 站点已禁用匿名访问,并且已启用 windows 身份验证。
但是。
没想到我的ASP.Net Core 2有一个“launchSettings.json
”文件,悄悄地藏在Properties
文件夹下,里面还有一些iisSettings,奇怪的是,这里的“windowsAuthentication
”默认设置为 false。
将“windowsAuthentication
”更改为 true,将“anonymousAuthentication
”更改为 false 解决了我的问题。
这样做之后,“User.Identity.Name
”终于包含了正确的用户名。
但是这个设置到底是什么?为什么 this 优先于我们在 IIS 管理器中设置的实际设置?!
使用 "DefaultIdentity"(个人用户帐户)也有这个问题(Core 3.1)。 User.Identity.Name 为空,User.Identity.IsAuthenticated = 真。 通过使用 httpContextAccessor,您可以获得 userId,并使用该 id 找到用户和 UserName。 在你的控制器中添加
using System.Security.Claims;
...
private readonly IHttpContextAccessor _httpContextAccessor;
public MyController(MyContext context, IHttpContextAccessor httpContextAccessor)
{
_context = context;
_httpContextAccessor = httpContextAccessor;
}
// Any method username needed
[HttpGet("{id}")]
public async Task<ActionResult<MyInfo>> GetMyInfo(int id)
{
var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
var user = _context.AspNetUsers.Find(userId);
var userName = user.UserName;
...
}
在 Startup.cs 中添加以下行:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
对于 Azure OAuth v2,使用 preferred_username 而不是 unique_name (see this and this)。
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
serviceCollection.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.RoleClaimType = "roles";
options.TokenValidationParameters.NameClaimType = "preferred_username";
//options.TokenValidationParameters.NameClaimType = "email"; // or if you want to use user's email for User.Identity.Name
//below lines of code can be removed. just there if you want some code to be executed right after user is validated.
options.Events.OnTokenValidated = async context =>
{
var personFirstName = context.Principal.FindFirstValue("given_name") ?? string.Empty;
var personLastName = context.Principal.FindFirstValue("family_name") ?? string.Empty;
var personEmail = context.Principal.FindFirstValue("email")?.ToLower();
var personName = context.Principal.Identity.Name;
};
});
然后在您的控制器中,您将从 User.Identity.Name
获取用户名