Как я могу применить безопасность на основе ролей к результатам запроса odata/breezejs?
Мне кажется, что запросы breeze / odata представляют значительный риск для безопасного доступа к данным. Например, предположим, что у меня есть неограниченный объект (U), который связан с ограниченным объектом (R). Я не буду выставлять конечную точку для запроса на R, и я напишу свой клиент для запроса на U без включения связанных R. Но злонамеренный клиент может запросить связанные рупии.
Как мне это предотвратить?
У меня есть пара идей. Но я пока не смог их реализовать, чтобы сказать, работают они или нет. Тем не менее, вот мои идеи:
1) Проверьте каждую полученную сущность - после того, как запрос был выполнен, но до того, как результат будет отправлен клиенту. Но я не знаю, как вставить свой проверочный код (через обратный вызов или что-то еще) в момент между выполнением и отправкой клиенту:(
2) Добавьте смарты в POCO, чтобы проверить наличие ограниченных объектов и свойств в зависимости от роли пользователя. Например, вместо:
class MyThing{
public string P {get;set;}
}
Я хотел бы что-то вроде этого:
private string _p;
public string P
{
get
{
if (UserRoles.HasAny("role-a","role-b"))
return _p;
return null;
}
set { _p = value; }
}
Это кажется странным, так как POCO должен быть тупым. POCO должен был бы иметь возможность читать роли пользователя откуда-то... может быть, сеанс HTTP. Я не совсем знаю, как это будет работать.
Я прочитал следующие вопросы / ответы, но они мне не помогают: безопасность на основе ролей в breezejs и EF6, как breeze.js управляет безопасностью и избегает разоблачения бизнес-логики, как обрабатывать авторизацию с помощью Breeze JS?
2 ответа
Вы можете использовать AllowedQueryOptions для предотвращения выполнения клиентом $expand
, как описано в этом SO ответе.
Другой способ - использовать ODataQueryOptions в качестве параметра для вашего метода контроллера WebAPI. Это дает вам подробную информацию о предикатах запроса в вашем методе сервера, так что вы можете применять их по мере необходимости, а не позволять WebAPI применять их автоматически. Это позволит вам расширить или нет, основываясь на запросе.
Посмотрите этот ответ и этот ответ, чтобы увидеть, как это работает.
Спасибо всем, кто прочитал мой вопрос, подумал об этом и даже зашел так далеко, что ответил. Но ничто не предложило работать для меня. Итак, я понял это самостоятельно. Я могу реализовать свой вариант № 1, подклассифицировать некоторые классы бриза. Я создаю подкласс EnableBreezeQueryAttribute, чтобы я мог переопределить NewQueryHelper для возврата моего подкласса QueryHelper. Затем я использую свой CustomEnableBreezeQueryAttribute в моих методах обслуживания. Метод ValidateData вызывается с объектами сущности. Я мог потерпеть неудачу в методе, если он содержит ограниченную информацию, или я мог бы убрать ограниченную информацию - разрешив возвращать неограниченную информацию.
public class CustomEnableBreezeQueryAttribute : EnableBreezeQueryAttribute
{
private class CustomQueryHelper : QueryHelper
{
public override IEnumerable PostExecuteQuery(IEnumerable queryResult)
{
queryResult = ValidateData(queryResult);
return base.PostExecuteQuery(queryResult);
}
private IEnumerable ValidateData(IEnumerable queryResult)
{
//TODO: validate/modify data
}
}
protected override QueryHelper NewQueryHelper()
{
return new CustomQueryHelper();
}
}
Я удивлен тем, как трудно было понять, как это сделать. И что не так просто ввести код на этом этапе. Оставляет меня с мучительными вопросами: я делаю что-то, что не должно быть сделано? Или это действительно дыра в функциональности odata/breeze? Или это то, как все делается в odata/breeze?