我是MVC3的新手。我正在寻求以下建议:
需要:
由于 阿伦
答案 0 :(得分:5)
我只是发布了我尝试过的代码。这只是我采取的一种方法。但是我需要epxperts评论来说明这对于安全性,性能等是否是好主意。
步骤1:继承IPrincipal的定义自定义接口
public interface ICustomPrincipal : IPrincipal
{
string[] Roles { get; set; }
string Country { get; set; }
string Region { get; set; }
string Department { get; set; }
string CurrentProductId { get; set; }
bool HasAcceptedTerms { get; set; }
}
步骤2:使用上面的接口
实现自定义主体public class CustomPrincipal : ICustomPrincipal
{
private IPrincipal principal;
public CustomPrincipal(IPrincipal principal, WindowsIdentity identity)
{
this.Identity = identity;
this.principal = principal;
}
#region IPrincipal Members
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
return (principal.IsInRole(role));
}
public string Department { get; set; }
public string[] Roles { get; set; }
public string Country { get; set; }
public string Region { get; set; }
public string CurrentProductId { get; set; }
public bool HasAcceptedTerms { get; set; }
#endregion
}
第3步:定义自己的角色提供者。同时为此提供程序创建web.config条目,并将其设置为默认提供程序
public class MyCustomRoleProvider : RoleProvider
{
List<string> _roles = new List<string> { "System Administrators", "Product Administrators", "Users", "Guests" };
public override string[] GetRolesForUser(string username)
{
//TODO: Get the roles from DB/Any other repository and add it to the list and return as array
return _roles.ToArray();
}
public override bool IsUserInRole(string username, string roleName)
{
if (_roles.Contains(roleName))
{
//this.Department = "My Department";
return true;
}
else
return false;
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
}
第4步:在事件下实施
注意:我正在将其他用户信息序列化到FormsAuthenticationTicket中。我的网站启用了Windows身份验证。
protected void WindowsAuthentication_OnAuthenticate(Object source, WindowsAuthenticationEventArgs e)
{
if (null == Request.Cookies.Get("authCookie"))
{
var userId = e.Identity.Name;
//TODO: You may need to get the user details like country, region etc. from DB. For simplicity, I have just assigned user roles (multiple) property
//Instead of string array, you should use your own Class to hold this custom data and then serialize
string[] userRoles = new string[] { "System Administrators", "Users" };
StringWriter writer = new StringWriter();
XmlSerializer xs = new XmlSerializer(typeof(string[]));
xs.Serialize(writer, userRoles);
FormsAuthenticationTicket formsAuthTicket =
new FormsAuthenticationTicket(
1,
userId,
DateTime.Now,
DateTime.Now.AddMinutes(20),
false,
writer.ToString());
var encryptedTicket = FormsAuthentication.Encrypt(formsAuthTicket);
HttpCookie httpCookie = new HttpCookie("authCookie", encryptedTicket);
Response.Cookies.Add(httpCookie);
}
}
步骤5:使用PostAuthenticateRequest事件将您的RolePrincipal包装为CustomPrincipal。这对于在Principal对象中保存数据是必要的,以便您可以在应用程序的任何部分中访问它。不要使用Application_AuthenticateRequest来包装WINDOWS主要对象。如果您启用角色提供程序,ASP.NET将实际替换具有角色主要功能的WINDOWS主页。
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies.Get("authCookie");
FormsAuthenticationTicket formsAuthenticationTicket = FormsAuthentication.Decrypt(authCookie.Value);
CustomPrincipal newUser = new CustomPrincipal(User, (WindowsIdentity)User.Identity);
StringReader sr = new StringReader(formsAuthenticationTicket.UserData);
XmlSerializer xs = new XmlSerializer(typeof(string[]));
object ret = xs.Deserialize(sr);
newUser.Roles = (string[]) ret;
Context.User = newUser;
}
根据Preben的建议,每当用户切换到不同的产品时,我都会更新cookie。
希望这对那些愿意将其他用户数据与Windows身份验证结合使用的人有所帮助。
如果有更好的方法来实现目标,请告诉我。
答案 1 :(得分:1)
您可以使用自定义主体和标识将其他数据附加到您的用户。使用自定义成员资格提供程序,您可以在身份验证时从数据库加载数据。
何时进行产品更改,您可以从当前线程中获取用户,并且可以调用您在自定义标识上编写的方法User.UpdateProducts()
。
这是Example