У нас есть сервис, который обрабатывает авторизацию на основе имени пользователя и пароля. Вместо того, чтобы вводить имя пользователя и пароль в вызов, мы помещаем его в заголовок SOAP.
В типичном сценарии веб-служба вызывает службу авторизации в начале выполнения, чтобы проверить, разрешено ли вызывающей стороне вызывать ее. Однако проблема в том, что некоторые из этих веб-служб вызывают друг друга, и это будет означать, что при каждом дополнительном вызове проверяются разрешения пользователя, и это может быть очень дорого.
Я подумал о том, чтобы служба авторизации возвратила токен безопасности после первого вызова. Затем вместо того, чтобы каждый раз вызывать службу авторизации, веб-служба может локально проверять заголовок безопасности.
Заголовок безопасности выглядит примерно так (код C # - обрезан, чтобы проиллюстрировать основную концепцию):
public sealed class SecurityHeader : SoapHeader
{
public string UserId; // Encrypted
public string Password; // Encrypted; Just realized this field isn't necessary [thanks CJP]
public DateTime TimeStamp; // Used for calculating header Expiry
public string SecurityToken;
}
Общая идея заключается в том, что SecurityHeader проверяется при каждом вызове. Если он существует, срок его действия не истек, а SecurityToken действителен, то веб-метод работает как обычно. В противном случае он либо возвратит ошибку, либо попытается повторно авторизоваться и сгенерировать новый SecurityHeader
SecurityToken основан на соленом хеше UserId, Password и TimeStamp. Соль меняется каждый день, чтобы предотвратить повторы.
Единственная проблема, которую я вижу, заключается в том, что у пользователя может быть разрешение на доступ к веб-службе A, но не к веб-службе B. Если он вызывает A и получает токен безопасности, как он сейчас стоит, это означает, что B пропустит его если он использует тот же токен. Я должен изменить его так, чтобы маркер безопасности действовал только от веб-службы к веб-службе, а не от пользователя к веб-службе, т.е. Должно быть в порядке, если пользователь вызывает A, который вызывает B, но не OK, если пользователь вызывает Службу A, а затем Службу D. Обходным путем является назначение общего ключа (или набора ключей) для логически связанных служб. (т.е. если клиент может сделать A, то логически он может сделать также B).
В качестве альтернативы мне придется кодировать весь набор разрешений пользователя как часть заголовка безопасности. Мне придется выяснить, какие будут накладные расходы.
Edit:
Несколько человек упоминали, что смотрели на другие схемы безопасности, такие как WS-Security, SAML и т. Д. У меня уже есть. На самом деле, я получил идею от WS-Security. Проблема заключается в том, что другие схемы не обеспечивают необходимую мне функциональность (кэширование информации об авторизации и защита от повторов без промежуточной базы данных). Если кто-то знает схему, которая это делает, я с радостью воспользуюсь ею. Кроме того, это не об аутентификации. Это обрабатывается другим механизмом, не зависящим от меня.
Если выясняется, что нет способа кэшировать данные авторизации, то это означает, что мне просто придется нести издержки авторизации на каждом уровне.