基于声明的表单身份验证角色
本文关键字:表单 身份验证 角色 声明 于声明 | 更新日期: 2023-09-27 17:56:35
我正在尝试使用 MVC 4 中的表单身份验证对用户进行身份验证(我使用的是 RavenDB,因此无法使用标准成员资格提供程序)。 然后稍后我使用 User.IsInRole()
方法或AuthorizeAttribute
来验证用户是否具有员工角色。
这是我在成功身份验证时设置票证的地方(目前在UserController.cs
):
FormsAuthenticationTicket ticket =
new FormsAuthenticationTicket(
1,
model.Email,
DateTime.Now,
DateTime.Now.AddDays(1),
false,
model.Email);
string hashedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie =
new HttpCookie(
FormsAuthentication.FormsCookieName,
hashedTicket);
HttpContext.Response.Cookies.Add(cookie);
这是我检查每个请求的票证的地方(Global.asax
):
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var user = this.UserService.GetUserByEmail(authTicket.Name);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, user.Roles);
HttpContext.Current.User = principal;
}
}
如果我随后在我的一个操作方法(CalendarController.cs)上放置一个调试点,我会得到等于false
isStaff
:
public ActionResult Index()
{
var user = HttpContext.User;
bool isStaff = user.IsInRole(Role.Staff);
return View();
}
只是为了完成(角色.cs,只是一个测试事物的临时类):
public static class Role
{
public static string Staff
{
get { return "Staff"; }
}
public static string Manager
{
get { return "Manager"; }
}
}
谁能帮我说一下我可能错过了什么? 看起来,当我到达操作方法时,我设置的角色似乎正在消失。
谢谢大家帮助我解决这个问题,我想出的(包含在下面)效果很好! 如果用户具有有效的票证 (cookie),它会直接通过登录屏幕自动登录用户,并且还使用 ClaimsIdentity
和 ClaimsPrincipal
对象处理基于声明的角色,而无需将角色放入用户的 cookie 中。 它还处理Global.asax.cs
文件中的身份验证,而无需诉诸于输入自定义授权属性。
用户控制器.cs
public ActionResult Login()
{
LoginViewModel model = new LoginViewModel();
if ((HttpContext.User != null) &&
(HttpContext.User.Identity.IsAuthenticated))
{
return RedirectToAction("Index", "Home");
}
return View(model);
}
[HttpPost]
public ActionResult Login(LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
bool isAuthenticated = this.userService.IsPasswordValid(model.Email, model.Password);
if (!isAuthenticated)
{
ModelState.AddModelError("AuthError", Resources.User.Login.AuthError);
return View(model);
}
FormsAuthentication.SetAuthCookie(model.Email, model.RememberUser);
return RedirectToAction("Index", "Home");
}
全球.asax.cs
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
FormsIdentity formsIdentity = new FormsIdentity(ticket);
ClaimsIdentity claimsIdentity = new ClaimsIdentity(formsIdentity);
var user = this.UserService.GetUserByEmail(ticket.Name);
foreach (var role in user.Roles)
{
claimsIdentity.AddClaim(
new Claim(ClaimTypes.Role, role));
}
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
HttpContext.Current.User = claimsPrincipal;
}
}
既然你正在使用Raven,我假设你做了自己的自定义MemberProvider和RoleProvider;并修改了web.config来使用它们。 您应该有一个类似于以下内容的条目:
<membership defaultProvider="MyMembershipProvider">
<providers>
<add name="MyMembershipProvider" type="namespace.MyMembershipProvider, providerAssemblyName" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="DefaultRoleProvider">
<providers>
<add connectionStringName="DefaultConnection" applicationName="/" name="DefaultRoleProvider" type="namespace.MyRoleProvider, providerAssemblyName" />
</providers>
</roleManager>
如果您使用的是 .NET Framework 4.5 版,则它使用基于声明的安全性,并且您不需要将角色存储在 Cookie 中。相反,角色只是存储在 ClaimsPrincipal 中的另一个声明。 现在,所有主体都继承自 ClaimsPrincipal,并且存储在
System.Web.HttpContext.Current.User as ClaimsPrincipal
如果成员资格和角色提供程序设置正确 ASP.NET 则应使用它们来填充 ClaimsPrincipal 中的角色,然后在选中 IsInRole 时检查声明。
还可以从声明主体中检索此类角色的角色。
principal.FindAll(ClaimTypes.Role).Select(p => p.Value);
您可以像这样向 ClaimsPrincipal 添加角色。
List<Claim> claims = new List<Claim>();
foreach (string role in roles)
claims.Add(new Claim(ClaimTypes.Role, role));
ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Forms"));
现在,您可以在身份验证后像这样设置cookie。
FormsAuthentication.SetAuthCookie(username, false);
您没有创建 FormsAuthenticationTicket 插入角色信息:
var ticket = new FormsAuthenticationTicket(
1, //ticket version
userName,
DateTime.Now,
DateTime.Now.Add(timeout), //timeout
true, //persistent cookies
roles,// <---ROLES not model.Email
FormsAuthentication.FormsCookiePath);
------编辑-----
忘记我说的话:我认为你调用IsInRole()太早了或用户。角色具有错误的值(可能是字符串中的空格:isinrole 使用 StringComparison.OrdinalIgnoreCase),或者您应该使用 FormsIdentity 而不是 GenericIdentity。
调试器说什么?
供参考:http://pastebin.com/jkqqcg28(这是我用于处理身份验证的起始模型)