我有一个问题一直困扰着我一段时间(我离开了一段时间,但现在我又回来了,我仍然无法找到解决方案)。
设置如下:我没有使用默认会员资格,角色或资料提供程序。相反,我的应用程序仅使用OpenID登录,它不实现密码。此外,我的users表使用ID作为主键,而不是用户名。
就身份验证而言,表单身份验证很棒,但是,某些操作要求我知道当前登录用户的ID。这会产生一个问题,因为表单身份验证只设置User属性中的Name(可在控制器User属性中访问,特别是在User.Identity.Name中)。
我最好喜欢像User.Identity.ID这样的东西,以便它可以包含在cookie中(如果我没有错),因为这是我的用户表的主键。
我在AccountController的登录方法中使用的是下面的丑陋和笨拙的事情
user = _userRepository.GetByOpenId(identifier);
FormsAuthenticationTicket ticket =
new FormsAuthenticationTicket(1, user.DisplayName,
DateTime.Now,
DateTime.Now.AddDays(10),
false /*rememberMe*/,
user.UserID.ToString());
稍后当我需要获取用户ID时:
int loggedUserID = Convert.ToInt32(((FormsIdentity)User.Identity).Ticket.UserData);
我基本上在Forms Cookie中对ID进行了编码,但除了让我感觉很脏之外,我还没有看到如何对此进行单元测试(如何在需要的地方提供假用户,包括其他控制器)。
总而言之,我在这里有两个问题:
请帮助我,谢谢!
编辑:有没有办法将User.Identity.Name属性更改为User.Identity.ID或添加新属性以使其具有语义感?
答案 0 :(得分:1)
您应该使用User.Identity.Name
属性来存储用户的唯一标识符,在您的情况下,该标识符是用户ID而不是其实际名称。
您可以通过创建新的GenericPrincipal
来测试User.Identity
var principal = new GenericPrincipal(new GenericIdentity(user.ID.ToString()), user.Roles.ToArray());
答案 1 :(得分:1)
编辑:在MVC3的DI-able控制器和test helper's InitializeController之后不再需要这个东西
我找到了一种单元测试依赖于用户的操作的方法,如Scott Hanselman's post所示。
总结一下,您可以像这样创建一个IPrincipal模型绑定器:
public class IPrincipalModelBinder : IModelBinder{
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
if (controllerContext == null) {
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null) {
throw new ArgumentNullException("bindingContext");
}
IPrincipal p = controllerContext.HttpContext.User;
return p;
}
}
然后在global.asax中注册binder:
void Application_Start() {
RegisterRoutes(RouteTable.Routes); //unrelated, don't sweat this line.
ModelBinders.Binders[typeof(IPrincipal)] = new IPrincipalModelBinder();
}
现在可以创建一个以IPrincipal为参数的动作:
public ActionResult Edit(int id, IPrincipal user)
在测试时传递假用户:
[TestMethod]
public void EditAllowsUsersToEditDinnersTheyOwn()
{
// Arrange
DinnersController controller = new DinnersController(new TestDinnerRespository());
// Act
IPrincipal FakeUser = new GenericPrincipal(new GenericIdentity("Scott","Forms"),null);
ViewResult result = controller.Edit(4, FakeUser) as ViewResult;
// Yada yada yada assert etc etc etc
Assert.IsTrue(result.ViewName != "InvalidOwner");
}