如何在 aspnet 身份中进行会话管理?
How to do session management in aspnet identity?
我正在使用Asp.net身份进行登录、注册、忘记密码等,源代码取自下面的link:
现在我有 1 个 table 是 UserMaster,在注册期间我要求输入以下字段:
全名、电子邮件 ID、密码、联系电话、性别。
我的 UserMaster 包含以下字段:Id,FullName,EmailId,ContactNumber,Gender
现在,当用户提交注册表时,此 FullName、EmailId、ContactNumber、Gender 将与 Email、Password 一起保存在 UserMaster 中AspnetUser.
我的注册方法和上面2link提供的一样
在这里你可能会注意到 我的 UserMaster 和 AspnetUser 之间没有关系 所以在登录期间当用户输入他的电子邮件 ID 登录时我将使用这种方法 await SignInManager.PasswordSignInAsync
来验证用户,如果此方法 returns 成功,那么我要做的是使用此电子邮件 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 身份执行此操作?
你可以这样做:
var fetchUser = context.UserMaster.Where(t => t.Email == model.Email).SingleOrDefault();
if (null == fetchUser)
throw new Exception("Not found");
Session["User"] = fetchUser;
由于您使用的是 Asp.Net 身份,因此您希望将与会话相关的内容存储为声明。这很容易通过自定义声明进行扩展。
顺便说一句,我认为你最好简单地扩展 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);
}
注意:我们正在使用自定义声明类型,以便我们保留现有的 NameIdentifier
和 Name
声明,因此可以轻松地从两个 Asp.Net Identity [=48] 访问身份信息=]和我们的习惯UserMaster
table.
步骤 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
,然后 return 我们找到的给定 CustomClaimType
的第一个声明的值,或者我们 return null
如果声明不存在。
第 4 步 - 现在我们可以非常轻松地访问视图 and/or 控制器中的自定义声明数据。假设您想使用 UserMaster
table 中的全名而不是 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>
您也可以在控制器中执行相同的操作。
您可以添加为:
var listClaims=new[] { new Claims(ClaimsType.SerialNumber,Id), new Claims(ClaimsType.Name,FullName), new Claims(ClaimsType.HomePhone,ContactNumber), new Claims(ClaimsType.Gender,Gender)};
var oAuthIdentity=new ClaimsIdentity(listClaims, otherparameter ...);
更多详情请查看System.Secutity.Claims.ClaimTypes
我正在使用Asp.net身份进行登录、注册、忘记密码等,源代码取自下面的link:
现在我有 1 个 table 是 UserMaster,在注册期间我要求输入以下字段: 全名、电子邮件 ID、密码、联系电话、性别。
我的 UserMaster 包含以下字段:Id,FullName,EmailId,ContactNumber,Gender
现在,当用户提交注册表时,此 FullName、EmailId、ContactNumber、Gender 将与 Email、Password 一起保存在 UserMaster 中AspnetUser.
我的注册方法和上面2link提供的一样
在这里你可能会注意到 我的 UserMaster 和 AspnetUser 之间没有关系 所以在登录期间当用户输入他的电子邮件 ID 登录时我将使用这种方法 await SignInManager.PasswordSignInAsync
来验证用户,如果此方法 returns 成功,那么我要做的是使用此电子邮件 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 身份执行此操作?
你可以这样做:
var fetchUser = context.UserMaster.Where(t => t.Email == model.Email).SingleOrDefault();
if (null == fetchUser)
throw new Exception("Not found");
Session["User"] = fetchUser;
由于您使用的是 Asp.Net 身份,因此您希望将与会话相关的内容存储为声明。这很容易通过自定义声明进行扩展。
顺便说一句,我认为你最好简单地扩展 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);
}
注意:我们正在使用自定义声明类型,以便我们保留现有的 NameIdentifier
和 Name
声明,因此可以轻松地从两个 Asp.Net Identity [=48] 访问身份信息=]和我们的习惯UserMaster
table.
步骤 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
,然后 return 我们找到的给定 CustomClaimType
的第一个声明的值,或者我们 return null
如果声明不存在。
第 4 步 - 现在我们可以非常轻松地访问视图 and/or 控制器中的自定义声明数据。假设您想使用 UserMaster
table 中的全名而不是 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>
您也可以在控制器中执行相同的操作。
您可以添加为:
var listClaims=new[] { new Claims(ClaimsType.SerialNumber,Id), new Claims(ClaimsType.Name,FullName), new Claims(ClaimsType.HomePhone,ContactNumber), new Claims(ClaimsType.Gender,Gender)};
var oAuthIdentity=new ClaimsIdentity(listClaims, otherparameter ...);
更多详情请查看System.Secutity.Claims.ClaimTypes