Как реализовать тестируемую пользовательскую систему на основе пользовательских идентификаторов в ASP.NET MVC при использовании проверки подлинности с помощью форм? - PullRequest
2 голосов
/ 10 марта 2011

У меня есть проблема, которая беспокоила меня уже довольно давно (я оставил ее на некоторое время, но теперь, когда я вернулся, я все еще не могу найти решение).

Настройкаэто так: я не использую членство, роль или профиль провайдеров по умолчанию.Скорее мое приложение использует только логин OpenID, оно не реализует пароли.Кроме того, в моей таблице пользователей в качестве первичного ключа используется идентификатор, а не имя пользователя.

Что касается проверки подлинности, то проверка подлинности с помощью форм является отличным решением, однако для некоторых действий требуется знать идентификатор текущего пользователя, вошедшего в систему.Это создает проблему, поскольку проверка подлинности с помощью форм устанавливает только имя в свойстве пользователя (доступно в свойстве пользователя контроллеров, в частности в 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());

И позже, когда мне нужно было получить идентификатор пользователя:

int loggedUserID = Convert.ToInt32(((FormsIdentity)User.Identity).Ticket.UserData);

Я в основном закодировал идентификатор в форм-куки, но помимо того, что я чувствовал себя грязным, я нене вижу, как выполнить это модульное тестирование (как предоставить фальшивого пользователя, где это необходимо, включая другие контроллеры).

Итак, подведем итог, у меня есть две проблемы:

  1. Каксделать это проще и менее хитрым (например, установить что-то как User.Identity.ID или аналогичный по простоте)
  2. Как сделать его тестируемым (в частности, как предоставить фальшивого пользователя, где это необходимо)

Пожалуйста, помогите мне, спасибо!

РЕДАКТИРОВАТЬ: Есть ли способ изменить свойство User.Identity.Name на User.Identity.ID или добавитьновое свойство, чтобы оно имело смысловой смысл?

Ответы [ 2 ]

1 голос
/ 07 апреля 2011

РЕДАКТИРОВАТЬ: Больше нет необходимости в этой вещи после контроллеров DI-способных MVC3 и InitializeController помощника тестирования


Я нашел способ модульного тестированиядействие, зависящее от пользователя, как показано в сообщении Скотта Хансельмана .

Подводя итог, вы создаете подшивку модели 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:

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");
}
1 голос
/ 10 марта 2011

Вы должны использовать свойство User.Identity.Name для хранения уникального идентификатора вашего пользователя, который в вашем случае является идентификатором пользователя, а не его фактическим именем.

Вы можете проверить User.Identity, создавновый GenericPrincipal

var principal = new GenericPrincipal(new GenericIdentity(user.ID.ToString()), user.Roles.ToArray());
...