我正在尝试从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'
。
答案 0 :(得分:6)
Claim
个对象不仅仅是一个简单的字符串,而您在userClaimsList
中看到的是这些声明对象的列表。
声明主要是一对claim type和claim 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;