从HttpContext.User.Claims中提取值

时间:2018-05-01 17:25:59

标签: c# linq asp.net-core

我正在尝试从HttpContext.User.Claims中提取电子邮件地址,我想请求帮助以找到更好的方法来编写代码(可能使用LINQ?)

我现在这样做的方式看起来非常黑客。

var userClaimsList = HttpContext.User.Claims.ToList();

// List is of varying length but email is always 3rd from the bottom.
int emailPosition = userClaimsList.Count()-3; 
string searchString = "preferred_username: "; 

// dirtyEmail = "preferred_username: xyz@emailcom"
string dirtyEmail = userClaimsList[emailPosition].ToString();
string cleanEmail = dirtyEmail.Replace(searchString, "").ToLower().Trim();

我已尝试过推荐的in another post LINQ解决方案,但收到错误Operator == cannot be applied to operands of type 'Claim' and 'string'

2 个答案:

答案 0 :(得分:6)

Claim个对象不仅仅是一个简单的字符串,而您在userClaimsList中看到的是这些声明对象的列表。

声明主要是一对claim typeclaim value,当您查找有关用户的某些信息时,您应该使用声明类型来标识您要查找的用户属性。< / p>

你在代码中所做的是假设你要求的声明是倒数第三,这本身已经是一个危险的假设,因为你无法确定这将总是是case:声明通常被认为是无序的,你应该按类型查找。一旦获得类型,然后.ToString(),它基本上将Claim类型的所有信息减少为格式为claimType: claimValue的单个字符串。您可以使用它,但当对象本身作为访问声明值的更好方式时,效率非常低。

由于您要查找前缀"preferred_username: ",我认为preferred_username是您要查找的声明类型。在这种情况下,你可以这样查看这个说法:

var claim = HttpContext.User.Claims.First(c => c.Type == "preferred_username");
var emailAddress = claim.Value;

如果找不到具有该类型的索赔,First的使用将引发异常。如果您不想这样,可以使用FirstOrDefault,然后检查claim是否为null

还有一些帮助程序扩展,允许您直接提取声明。在这种情况下,您可以使用FindFirstValue直接获取声明值:

var emailAddress = HttpContext.User.FindFirstValue("preferred_username");

如果找不到具有该类型的声明,FindFirstValue将返回null,因此emailAddress在这种情况下可能为null

答案 1 :(得分:2)

你所做的不仅仅是假设你无法保证的东西,而且还要比你需要的更难:

// note: HttpContext.User == User
var cleanEmail = User.FindFirst(ClaimTypes.Email)?.Value;

如果数据不在email声明类型上,请检查相应的类型并改为使用。在您的情况下,它似乎应该是preferred_username

var cleanEmail = User.FindFirst("preferred_username")?.Value;