如何在aspnet身份中进行会话管理?

时间:2015-10-01 05:48:40

标签: c# asp.net-mvc asp.net-identity owin

我使用 Asp.net身份进行登录,注册,忘记密码等,源代码取自以下链接:

http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset

http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

现在我有1个UserMaster表,在注册期间我要求以下字段: 的全名,EMAILID,密码ContactNumber,性别

我的UserMaster包含以下字段: Id,FullName,EmailId,ContactNumber,Gender

现在,当用户提交此FullName,EmailId,ContactNumber的注册表时,性别将与电子邮件一起保存在 UserMaster 中,密码将保存在AspnetUser中。< / p>

我的注册方法与上述2个链接中提供的相同。

您可能会注意到我的UserMaster和AspnetUser之间存在没有关系,因此在登录时用户将输入他的电子邮件ID进行登录时,我将使用此方法await SignInManager.PasswordSignInAsync来验证用户和如果此方法返回成功,那么我将使用此电子邮件ID并在我的UserMaster中检查此电子邮件并找到匹配的地方我将从UserMaster获取UserId并将其存储在会话中并在我的登录方法中使用我的应用程序如下所示:

 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
            {
                if (!ModelState.IsValid)
                {
                    return View(model);
                }

                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, change to shouldLockout: true
                var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
                switch (result)
                {
                    case SignInStatus.Success:
                  using (var context = new MyEntities())
                        {
                            var fetchUSerId = context.UserMaster.Where(t => t.Email == model.Email).Select(t=>t.UserId).SingleOrDefault();
                            Session["UserId"] = fetchUSerId;
                        }
                        return RedirectToLocal(returnUrl);
                    case SignInStatus.LockedOut:
                        return View("Lockout");
                    case SignInStatus.RequiresVerification:
                        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                    case SignInStatus.Failure:
                    default:
                        ModelState.AddModelError("", "Invalid login attempt.");
                        return View(model);
                }
            }

我在登录方法中谈论这个:

 case SignInStatus.Success:
                      using (var context = new MyEntities())
                            {
                                var fetchUSerId = context.UserMaster.Where(t => t.Email == model.Email).Select(t=>t.UserId).SingleOrDefault();
                                Session["UserId"] = fetchUSerId;
                            }

这是一种合适的方式还是更好的方式,我希望存储整个用户对象,而不是仅存储用户ID。

那么有人能告诉我如何使用aspnet身份吗?

3 个答案:

答案 0 :(得分:24)

由于您使用的是Asp.Net Identity,因此您希望将与会话相关的内容存储为声明。通过自定义声明,这很容易扩展。

顺便说一下,我认为你最好简单地延长ApplicationUser来保存其他数据,详见here

也就是说,这是一个如何向您的应用程序添加自定义声明类型的完整示例。

第1步 - 定义一个或多个自定义声明类型以保存您的其他信息

public static class CustomClaimTypes
{
    public const string MasterFullName = "http://schemas.xmlsoap.org/ws/2014/03/mystuff/claims/masterfullname";
    public const string MasterUserId = "http://schemas.xmlsoap.org/ws/2014/03/mystuff/claims/masteruserid";
}

声明类型只是标识特定声明的唯一字符串。这里我们只使用与内置声明类型类似的格式。

第2步 - 在登录过程中,设置自定义声明类型的值

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    //Fetch data from the UserMaster table 
    var userdata = GetdatafromUserMaster();

    //Using the UserMaster data, set our custom claim types
    identity.AddClaim(new Claim(CustomClaimTypes.MasterUserId, userdata.UserId));
    identity.AddClaim(new Claim(CustomClaimTypes.MasterFullName, userdata.FullName));

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

注意:我们使用自定义声明类型,以便保留现有的NameIdentifierName声明,因此可以轻松地从Asp.Net Identity 和我们的自定义UserMaster表。

第3步 - 将扩展方法添加到IIdentity,以便我们轻松访问自定义声明数据

public static class IdentityExtensions
{
    public static string GetMasterUserId(this IIdentity identity)
    {
        if (identity == null)
            return null;

        return (identity as ClaimsIdentity).FirstOrNull(CustomClaimTypes.MasterUserId);
    }

    public static string GetMasterFullName(this IIdentity identity)
    {
        if (identity == null)
            return null;

        return (identity as ClaimsIdentity).FirstOrNull(CustomClaimTypes.MasterFullName);
    }

    internal static string FirstOrNull(this ClaimsIdentity identity, string claimType)
    {
        var val = identity.FindFirst(claimType);

        return val == null ? null : val.Value;
    }
}

这里没什么好看的。我们只是将IIdentity转换为ClaimsIdentity,然后返回我们找到的给定CustomClaimType的第一个声明的值,如果声明没有,我们会返回null不存在。

第4步 - 现在,我们可以非常轻松地访问视图和/或控制器中的自定义声明数据。假设您想使用UserMaster表格中的全名而不是ApplicationUser?你现在可以这样做:

<ul class="nav navbar-nav navbar-right">
    <li>
        @Html.ActionLink("Hello " + User.Identity.GetMasterFullName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
    </li>
    <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>

您也可以在Controller中执行相同的操作。

答案 1 :(得分:2)

您可以添加为:

var listClains=new[] { new Claims(ClainsType.SetiaNumber,Id), new Claims(ClainsType.Name,FullName), new Claims(ClainsType.HomePhone,ContactNumber), new Claims(ClainsType.Gender,Gender)};

var oAuthIdentity=new CalimsIdentity(listClains, otherparameter ...);

有关详细信息,请查看System.Secutity.Claims.ClaimTypes

答案 2 :(得分:1)

你可以这样做:

var fetchUser = context.UserMaster.Where(t => t.Email == model.Email).SingleOrDefault();
if (null == fetchUser)
    throw new Exception("Not found");
Session["User"] = fetchUser;