Как запретить пользователю изменять идентификатор в URL для доступа к другим записям?

#asp.net-mvc #url-routing

#asp.net-mvc #url-маршрутизация

Вопрос:

использование asp mvc 4.

Когда пользователь переходит к записи учащегося, URL-адрес говорит:

 http://studentTracker.org/Record/Student?studentId=380
  

В настоящее время пользователь может изменить идентификатор студента прямо в URL-адресе и получить эту запись students, если она не существует. Как я могу либо скрыть часть строки запроса URL-адреса, либо обнаружить / проверить на контроллере, если пользователь изменил URL-адрес?

Комментарии:

1. Я не работаю с asp, но попробуйте сохранить идентификатор пользователя в переменной сеанса или файле cookie, а затем сравнить значение сохраненной переменной со значением studentId . Если они не совпадают, перенаправьте пользователя куда-нибудь.

Ответ №1:

Во-первых, вы не можете запретить пользователю что-либо делать, особенно что-то вроде изменения идентификатора в URL. Что вы можете сделать, так это убедиться, что если они это сделают, они получат что-то вроде 404 или 403 вместо фактического содержимого.

Способ сделать это — выполнить разрешение на уровне объекта, что в основном просто означает привязку объекта к пользователям, которым разрешено каким-либо образом просматривать / редактировать его. Обычно это делается с помощью внешнего ключа для чего-то вроде вашего объекта «user» или чего-то более широкого, например, группы или роли.

Например, если запись «Student 380» принадлежит jdoe , то вы можете запретить доступ к ней кому-либо, но jdoe сначала добавив внешний ключ к вашей сущности «user» в вашей сущности «student». (Предполагается, что идентификатор не указан):

 public class Student
{
    ...

    [ForeignKey("Owner")]
    public string OwnerId { get; set; }
    public virtual ApplicationUser Owner { get; set; }
}
  

Затем в вашем действии вместо запроса только по идентификатору вы запрашиваете как идентификатор в URL, так и идентификатор аутентифицированного пользователя:

 var userId = User.Identity.GetUserId();
var student = db.Students.SingleOrDefault(m => m.Id == studentId amp;amp; m.OwnerId == userId);
if (student == null)
{
    return new HttpNotFoundResult();
}
  

Теперь, если пользователь изменяется studentId , но не установлен в качестве «владельца» соответствующего учащегося, он получит 404.

Комментарии:

1. Итак, в этой ситуации люди, которые могут просматривать записи учащихся, являются консультантами, и они оба имеют доступ ко всем записям учащихся. Таким образом, нет никаких оснований для того, чтобы они не могли этого сделать, на самом деле это нормально, что касается бизнес-правил. Просто кажется ужасно небезопасным, зачем вообще получать данные. Я имею в виду, нельзя ли скрыть параметры в заголовке или что-то в GET, чтобы они не были видны в URL?

2. Нет. HTTP работает не так. URI — это «уникальный идентификатор ресурса», здесь это то, studentId что делает его уникальным и позволяет серверу возвращать конкретного учащегося. Это также не «небезопасно». Во-первых, что-то вроде идентификатора не имеет собственного значения вне таблицы базы данных, и если кто-то может видеть таблицу базы данных, у вас есть гораздо более насущные проблемы, чем предоставление идентификатора в URL. Поскольку пользователь может манипулировать им, приложение всегда должно защитить себя от таких манипуляций, выполнив что-то вроде того, что я описал здесь.

3. установите для типа данных studentid значение guid, при котором будет очень сложно установить параметр вручную и получить информацию о пользователе