обеспечение авторизации запросов в linq-to-sql - PullRequest
4 голосов
/ 08 января 2012

У меня есть 3 таблицы: the User table, the Records table and the UserRecords table.

Столбцы такие:

UserTable
UserID | OtherUserDataFields

RecordsTable
RecordID | OtherRecordDataFields

UserRecords
UserID | RecordID

Таблица UserRecords сообщает мне, у каких пользователей есть авторизация для какой записи.У меня есть функция, которая обновляет RecordsTable, получая 2 параметра: запись TheRecord (которая содержит поле RecordID) и UserID.

Я пишу запрос в контексте данных MyDC, чтобы извлечь запись сRecordID предоставляется в параметре и проверяет, авторизован ли пользователь для этой записи следующим образом:

var RecordToUpdate = (
    from r in MyDC.RecordsTable
    from u in MyDC.UserRecords
    where r.RecordID == TheRecord.RecordID && TheRecord.RecordID == u.RecordID
    where u.UserID == TheUserID
    select r).SingleOrDefault();

Будет ли это гарантировать, что будут выбраны только записи, авторизованные пользователем?Я хочу избежать случаев, когда пользователи злонамеренно отправляют записи, на которые они не авторизованы, и вносят изменения в эти несанкционированные записи.

Спасибо за ваш совет.

Ответы [ 4 ]

3 голосов
/ 16 января 2012

Я согласен с Анандом, вам понадобится запрос linq:

var filterUserRecord = from u in MyDC.UserRecords
                       where u.UserID  == TheUserID
                       select u;

var q1 = from r in  MyDC.RecordsTable
          where r.RecordID = TheRecordID
          where filterUserRecord.Any(f => f.RecordID == r.RecordID)
          select r;

Это будет преобразовано в запрос SQL следующим образом:

SELECT * FROM RecordsTable rt WHERE rt.RecordID = TheRecordID AND EXISTS
   (SELECT recordId FROM UserRecords ur WHERE ur.userId = TheUserID AND ur.recordID = rt.recordID)

Обратите внимание, что это IQueryable<T> s, и запросы linq к нему создадут еще один IQueryable<T>, который будет содержать выражения для полного перевода в SQL (или какой бы то ни было серверной частью) вместо наивной оценки его на стороне клиента.

3 голосов
/ 10 января 2012

Ну, я думаю, что ваша проблема может быть решена с помощью подзапроса

sql:

select * from RecordsTable where recordId in 
(select recordId from UserRecords where userId = @someUserId)

Это может быть представлено в Linq следующим образом

var filterUserRecord = from u in MyDC.UserRecords
                       where u.UserID  == TheUserID
                       select u

var q1 = from r in  MyDC.RecordsTable
         where filterUserRecord.Any(f => f.RecordID == r.RecordID)

Подробности для подзапросав Linq - читать с здесь

2 голосов
/ 15 января 2012

Возможно, прочитайте статью здесь , в которой обсуждается, как SQL-инъекция (которая, я полагаю, должна быть здесь главной проблемой безопасности) обрабатывается в сценариях LINQ.

Есть также хорошая статья здесь , касающаяся соображений безопасности Microsoft для EF. Это стоит прочитать любому, кто разрабатывает эти инструменты!

[Изменить] Что касается вашего последнего комментария, вы можете использовать запросы, аналогичные тем, которые уже есть на этой странице. Для краткости: если ваша база данных нормализована, в той степени, в которой RecordId является уникальным первичным ключом, вы можете обойти объединения, чтобы сделать запрос, который выглядит немного лучше:

var targetRecords = 
    from userRecords in MyDC.UserRecords
    where userRecords.UserTable.UserID == TheUserID
    && userRecords.RecordsTable.RecordID == TheRecord.RecordID
    select userRecords;

var targetRecordsResult = targetRecords.SingleOrDefault();

Я отделил запрос от его результата 'var', чтобы указать, что 'targetRecords' НЕ будет оценен, пока вы не вызовете для него SingleOrDefault, чтобы назначить объект targetRecordsResult. Вы можете, конечно, обернуть это в одно утверждение, если хотите.

Если, как уже упоминалось, ваш RecordID является уникальным первичным ключом, вы получите либо обратно соответствующую запись, либо ноль. Обратите внимание, что если это не так, то есть больше, чем в записи, может иметь один и тот же идентификатор, то вызов SingleOrDefault может завершиться ошибкой. Если ваша база данных разработана таким образом, вам придется использовать запрос, более похожий на тот, который задал Ананд. Это немного более многословно, но вернет вам ЛЮБУЮ запись с соответствующим идентификатором для этого конкретного пользователя.

С точки зрения безопасности, обратите внимание, что ваш оператор SQL будет скомпилирован с идентификатором пользователя, что очень затруднит его вмешательство. Отсюда моя точка зрения, что в этом случае сфера действия и раскрытие идентификатора пользователя является вашей главной задачей. Если, как вы заявили, пользователь (и любой потенциальный злонамеренный пользователь) не имеет доступа к переменной (через раскрытие свойств и т. Д.), То это должно быть более чем подходящим для ваших нужд.

1 голос
/ 11 января 2012

Попробуйте это:

var RecordToUpdate = (from u in MyDC.UserRecords
                      where u.UserTable.UserID == TheUserID
                      and u.RecordsTable.RecordID == TheRecord.RecordID).SingleOrDefault();

Это вернет результат для запроса, который указал UserID и RecordID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...