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

时间:2013-12-05 04:43:04

标签: authentication ravendb asp.net-mvc-5 claims-based-identity katana

我在.NET MVC 5应用程序中工作。我不想使用Entity Framework。我想验证RavenDB数据库。在我看来,我想要替换帐户控制器附带的UserManager。我想我可以重写所有UserManager函数来使用我的数据库,除了我不理解ClaimsIdentity对象。

SignInAsync方法中,有一个UserManager.CreateIdentityAsync(...)的来电。我知道它返回一个ClaimsIdentity对象。我不知道的是如何自己创建一个ClaimsIdentity对象。

我发现它有4个属性ActorBootstrapContextClaimsLabel。我不知道这些属性用于什么,我不知道如何正确生成它们。我认为正确生成它们很重要,因为它是身份验证cookie的制作方式。

我查看了ClaimsIdentity对象here的解释,但这并没有真正帮助我理解。

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

如果我发现这一切都错了,请告诉我。否则,如果有人可以指出我如何生成ClaimsIdentity对象,那将会有所帮助。

ClaimsIdentity identity = new ClaimsIdentity
{
    Actor = ????,
    BootstrapContext = ?????,
    Claims = ?????,
    Label = ?????
}

5 个答案:

答案 0 :(得分:42)

也许following link可以提供帮助:

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);

答案 1 :(得分:20)

我认为你已经&#34;这一切都是错的&#34;。 ASP.NET Identity Framework在设计时考虑了可插入的持久性。将RavenDB替换为EF的正确方法不是替换UserManager。相反,它是实现替换UserStore。因此,创建AccountController的{​​{1}}中的行会改为:

UserManager

要:

public AccountController()
    : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))

public AccountController() : this(new UserManager<ApplicationUser>(new RavenDBUserStore<ApplicationUser>/* connection info here*/))) 将是您编写的实现RavenDBUserStoreIUserStore以及您的特定应用所需的任何其他* Store接口的类。

此方法可避免您需要了解并重新实施IUserPasswordStore中的所有内容,并确保您能够利用MS对UserManager的未来改进。

有关如何执行此操作的详细信息,请参阅Overview of Custom Storage Providers for ASP.NET IdentityImplementing a Custom MySQL ASP.NET Identity Storage Provider的示例。您还应该查看RavenDB.AspNet.Identity Nuget Package中提到的David Boike创建的answer代码。来源位于https://github.com/ILMServices/RavenDB.AspNet.Identity/tree/master/RavenDB.AspNet.Identity

的github上

答案 2 :(得分:9)

这是我想出的。我很想知道这是否是完成这项任务的正确方法。

在默认的MVC5网站上工作,我去了帐户控制器,找到了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()功能。

默认网站的LogIn / LogOff部分在这些调整后似乎工作正常。在我接受之前,我会在这里留下这个答案,以防有人告诉我为什么我不应该这样做。

答案 3 :(得分:6)

我为新的ASP.NET MVC 5 Identity创建了一个RavenDB实现,并将其作为NuGet包发布。这可能适合你。

http://www.nuget.org/packages/RavenDB.AspNet.Identity/

这有点预发布,但我在一个真实的项目中使用它。

以下是关于它的GitHub projectshort thread on the RavenDB discussion group

答案 4 :(得分:0)

我希望我没有在此处发布问题的问题,这不适合评论部分

@Katstevens看起来对您来说很对:我的队友找到了该解决方案并使用了很长时间,因此我也在自己的应用程序中实现了该解决方案,但是由于getUserId无法正常工作,因此我发现了这里的内容,然后在Global.aspx启动方法上将声明添加到我的自定义数据中:

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        CustomPrincipalSerializeModel serializeModel = JsonConvert.DeserializeObject<CustomPrincipalSerializeModel>(authTicket.UserData);
        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.UserId = serializeModel.UserId;
        newUser.UserName = serializeModel.UserName;
        newUser.NameFamily = serializeModel.NameFamily;
        newUser.IP = serializeModel.IP;
        newUser.roles = serializeModel.roles;
        HttpContext.Current.User = newUser;
        System.Threading.Thread.CurrentPrincipal = newUser;

        //Added by myself... (make UserId work as identity.GetUserId())
        (newUser.Identity as ClaimsIdentity)?.AddClaims(new List<Claim>{
            new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", authTicket.Name), //user.Name from my database
            new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", serializeModel.UserId), //user.Id from my database
            new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "RealEstate"), //MyApplication
        });
    }
}

是的,但是这样做是对的吗? 数据应该从哪里来,应该从哪里发生?等等.... 数据不可替代吗?和安全吗?