如何在Asp.NET MVC 5中创建一个ClaimsIdentity对象?

34

我正在使用.NET MVC 5应用程序。我不想使用Entity Framework。我想要对RavenDB数据库进行身份验证。看起来我想要替换Account Controller中提供的UserManager。我认为我可以重写所有UserManager函数以与我的数据库配合使用,但是我不理解ClaimsIdentity对象。

在SignInAsync方法中,调用了UserManager.CreateIdentityAsync(...)方法。我知道它返回一个ClaimsIdentity对象。我不知道如何自己创建ClaimsIdentity对象。

我看到它有4个属性Actor,BootstrapContext,Claims和Label。我不知道这些属性的用途,也不知道如何正确生成它们。我假设正确生成它们很重要,因为这是身份验证cookie的生成方式。

我查看了ClaimsIdentity对象的说明这里,但那并没有真正帮助我理解。

如果我可以看到CreateIdentityAsync()的代码,那可能会有帮助。

如果我做错了,请告诉我。否则,如果有人能指导我如何生成ClaimsIdentity对象,那将是有帮助的。

ClaimsIdentity identity = new ClaimsIdentity
{
    Actor = ????,
    BootstrapContext = ?????,
    Claims = ?????,
    Label = ?????
}
4个回答

56

也许这个链接能够帮助:

var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, "Brock"));
claims.Add(new Claim(ClaimTypes.Email, "brockallen@gmail.com"));
var id = new ClaimsIdentity(claims,DefaultAuthenticationTypes.ApplicationCookie);

var ctx = Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(id);

20
我认为你的做法“完全错误”。ASP.NET身份验证框架是以可插拔持久性为设计目标的。正确的方式不是替换UserManager,而是实现一个替代的UserStore。因此,在AccountController中创建UserManager的代码行将更改为:
public AccountController()
    : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))

To:

public AccountController()
    : this(new UserManager<ApplicationUser>(new RavenDBUserStore<ApplicationUser>/* connection info here*/)))

RavenDBUserStore 是您编写的一个类,实现了 IUserStoreIUserPasswordStore 以及您特定应用所需的所有其他 *Store 接口。

此方法避免了您需要理解和重新实现 UserManager 中的所有内容,并确保您能够利用来自 MS 的未来改进来提升性能。

有关如何执行此操作的更多信息,请参见自定义 ASP.NET Identity 存储提供程序概述以及实现自定义 MySQL ASP.NET Identity 存储提供程序示例。您还应该查看由David Boike创建的RavenDB.AspNet.Identity Nuget 包,他在答案中提到。源代码位于https://github.com/ILMServices/RavenDB.AspNet.Identity/tree/master/RavenDB.AspNet.Identity


1
我相信这是解决手头问题的正确答案,即“如何使用不同的数据存储与Identity 2.0”。重新实现自己的ClaimsIdentity而不完全理解如何以及为什么这样做只会在未来带来麻烦。对于理解框架的预期使用方式加1。 - Katstevens

9
这是我的想法。我很想知道这是否是完成此任务的正确方式。
在默认的MVC5网站中工作,我进入了Account控制器,并找到了SignInAsync()函数。我进行了以下调整:
    private async Task SignInAsync(ApplicationUser user, bool isPersistent)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        //var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); --> this is where I want to get rid of UserManager
        List<Claim> claims = new List<Claim>{
            new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", user.Name), //user.Name from my database
            new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", user.Id), //user.Id from my database
            new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "MyApplication"),
            new Claim("FirstName", user.FirstName) //user.FirstName from my database
        };
        ClaimsIdentity identity = new System.Security.Claims.ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);

        AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }

请记住,这还需要更改[HttpPost] Login函数,从我的数据库中获取用户,而不是使用UserManager.FindAsync()函数。
在进行这些调整后,默认站点的登录/注销部分似乎正常工作。在接受此答案之前,我会将其保留一段时间,以便有人可以告诉我为什么不应该这样做。

1
虽然人们在不完全理解这种方法的情况下使用它的后果让我感到害怕,但其他人应该研究ClaimTypes枚举以生成模式URI:特别是ClaimTypes.NameIdentifier,它将生成“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”等。 - Katstevens
你会详细阐述一下这种“方法”的“后果”吗? - Worthy7

6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接