Использование IParameterInspector, чтобы остановить неавторизованного пользователя для чтения данных без надлежащего доступа в WCF
У меня есть служба WCF и несколько операций, где я возвращаю массивы основных элементов poco.
Чтобы смягчить случаи, когда я по ошибке возвращаю элементы, к которым у клиента нет доступа, я планировал использовать IParameterInspector, присоединить его к атрибуту IOperationBehavior и затем проверить доступ на чтение в AfterCall. Если у клиента нет прав на чтение, я выкидываю исключение WebFaultException.
Я использую настраиваемую аутентификацию в своем репозитории элементов (класс обслуживания), и ServiceSecurityContext имеет значение null, когда я вхожу в IParameterInspector.AfterCall, поэтому я не могу использовать это для проверки подлинности клиента для чтения элементов.
У меня вопрос, как мне получить доступ к экземпляру службы (PerCall) в моем методе IParameterInspector.AfterCall?
Я также использую IOperationInvoker, где я делаю настоящую аутентификацию в Invoke-методе (проверьте, какой пользователь или анонимус).
И мне интересно, какая разница между "выходами" и "returnValue" в AfterCall?
public class ParameterInspector : IParameterInspector
{
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
var items = returnValue as Item[];
if (items == null) return;
foreach (var item in items)
{
User user = ?
// Throw if no access
}
}
public object BeforeCall(string operationName, object[] inputs)
{
return inputs;
}
}
public class AuthenticationOperationInvoker : IOperationInvoker
{
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var repo = instance as RepositoryBase;
User user;
repo.Authenticate(out user);
return _defaultInvoker.Invoke(instance, inputs, out outputs);
}
}
1 ответ
Вы пробовали OperationContext.Current.ServiceSecurityContext.PrimaryIdentity?
Редактировать:
string MyFunction( AThing something, BThing another )
В этом случае returnValue является строкой, возвращаемой MyFunction. На выходе будет что-то и другое.
Сложность в общем подходе, таком как использование инспектора параметров, состоит в том, что он часто варьируется от объекта к объекту, как вы будете определять, разрешено ли пользователю видеть объект или какие свойства ему разрешено видеть.
Подход, который я обычно использовал бы для этого (не зная специфики домена), заключается в том, чтобы передавать идентификационную информацию пользователя в хранилище и иметь хранилище, отвечающее за то, чтобы возвращалась только информация, к которой имеет доступ пользователь.
Возьмите, например, если у вас было следующее:
public class GroupTrip
{
public string GroupName {get;set;}
public DateTime Start {get;set;}
public List<Person> Attendees {get;set;}
public Person Organizer {get;set;}
public bool IsStandBy {get;set;}
}
public class Person
{
public string Name {get;set;}
public string Phone {get;set;}
}
И вы должны убедиться, что:
- Вы можете видеть объект группы, только если вы посещаете.
- Если вы посещаете, вы должны видеть имена других людей, но не их номера телефонов
- Если вы посещаете, вы должны увидеть имя организатора и номер телефона.
- Если вы посещаете, вы не должны видеть никого в режиме ожидания
- Если вы организатор, вы сможете увидеть номер телефона каждого.
Это может быстро стать очень сложным. Помогает перенести сложность в хранилище.