Как я могу делегировать проверки авторизации JAAS в Shiro?


Я разрабатываю серверное приложение, которое нуждается в аутентификации и авторизации на основе объектов. Мне нравится простота Shiro, но для совместимости с JAAS я написал LoginModule, который использует Apache Shiro в качестве базового механизма.

но моя проблема в том, что я не мог найти способ делегировать проверки авторизации JAAS в Shiro. Как я могу этого достичь?

1 63

1 ответ:

Примечание: ответ касается общего случая, когда внешняя система авторизации должна быть интегрирована с JVM, с помощью стандартной системы безопасности. Он не является специфичным для Shiro или JMX, поскольку я не знаком ни с одним из них.


концептуально, кажется, что вы находитесь после точки принятия политических решений (PDP) -- объект, где запросы авторизации ("является юридическим лицом х позволило сделать y?") оцениваются, то есть. Данный пакет предлагает несколько эти:

  1. эффективное SecurityManager, в частности checkXXX группа методов.
  2. The ProtectionDomain класс, особенно его implies(Permission) метод.
  3. ключ implies(ProtectionDomain, Permission) метод эффективного Policy.
  4. кроме того,implies способы CodeSource,PermissionCollection,Permission, и Principal.

любой из вышеупомянутых методов может быть переопределен для настройки, при возрастающей детализации, функциональности концептуального PDP. Следует отметить, что JAAS сделал (вопреки тому, что предполагает его название) на самом деле не принес свой собственный PDP; скорее, он предоставил означает для домена и политики для поддержки запросов, основанных на принципе, в дополнение к исходному коэффициенту доверия источника кода. Поэтому, на мой взгляд, ваш требование сохранения "JAAS-совместимого" в основном переводится на желание использовать (original-plus-JAAS) модель авторизации Java SE, a.k.a. the песочница, которая я сомневаюсь, чтобы быть то, что вы хотите. Фреймворки, такие как Shiro, как правило, используются, когда стандартная модель считается либо слишком низкоуровневой и/или интенсивной по производительности; другими словами, когда логика авторизации не нужно оценить каждый кадр стека для данного набора факторов доверия, из-за этих факторов будучи чаще контекстно-нечувствительным, чем нет. В зависимости от обоснованности моего предположения, для рассмотрения возникают три основных случая:

  1. авторизация AccessControlContext-независимые. Атрибуты авторизации Shiro-native (SNAAs), какими бы они ни были, применяются ко всему потоку. Происхождение кода не имеет значения.
  2. происхождение кода имеет значение, обязательное использование песочницы. СНС все еще AccessControlContext-независимые.
  3. начало кода и Снсас оба уместны и AccessControlContext -зависимая.

1. Авторизация основана исключительно на SNAAs

  1. управление аутентификацией, как вы считаете нужным. Если вы хотите продолжать использовать JAAS'javax.security.auth SPI для аутентификации, забудьте о создании стандарта Subject в качестве результата проверки подлинности, вместо этого напрямую связывая Shiro-specific с потоковым локальным хранилищем. Таким образом, вы получите более удобный доступ к SNAAs, и избежать необходимости использовать AccessControlContext (и страдать потенциал производительность), для их извлечения.
  2. подкласс SecurityManager, переопределяя по крайней мере два checkPermission методы такие, что они

    1. перевести, если необходимо, то Permission аргумент в чем-то PDP Широ (SPDP) понимает, до
    2. делегирование в SPDP с потоком-локальными SNAAs и разрешением (и бросание SecurityException должен ли доступ к сигналу SPDP отрицание.)

    перегрузка приема контекста безопасности может просто игнорировать соответствующий аргумент. Во время инициализации приложения создайте экземпляр и установите (System::setSecurityManager) своего осуществления.


2. Гибридная авторизация, сочетающая происхождение кода с контекстно-нечувствительным SNAAs

  1. управление аутентификацией, как вы считаете нужным; еще раз связать Широ-конкретные Subject с ниткой себя.
  2. подкласс SecurityManager, переопределяя по крайней мере два checkPermission методы, на этот раз такие, что они делегируют как SPDP, так и/или переопределенную реализацию (которая, в свою очередь, вызывает checkPermission on, соответственно, текущий или поставляемый контекст управления доступом). Какой из них (ов) и в каком порядке следует консультироваться для любого данного разрешения, конечно, зависит от реализации. Когда оба должны быть вызваны, SPDP должен быть запрошен сначала, так как он, вероятно, ответит быстрее чем контекст управления доступом.
  3. если SPDP должен дополнительно обрабатывать оценку разрешений, предоставленных коду, происходящему из определенного местоположения и / или набора подписчиков кода, вам также придется подкласс Policy, осуществляет implies(ProtectionDomain, Permission) такие, что как SecurityManager::checkPermission выше он передает некоторое понятное представление домена (обычно только его CodeSource) и аргументы разрешения - но логически не SNAAs -- к SPDP. Реализация должна быть эффективно, насколько это возможно, так как он будет вызываться один раз на домен в контексте управления доступом в checkPermission времени. Создать экземпляр и установить (Policy::setPolicy) своего осуществления.

3. Гибридная авторизация, сочетающая происхождение кода с SNAAs, как контекстно-зависимые

  1. управление аутентификацией, как вы считаете нужным. К сожалению, часть обработки темы не так тривиальна, как создание ThreadLocal в этом случае.
  2. подкласс, создать и установить Policy который выполняет объединенные обязанности SecurityManager::checkPermission и Policy::implies, как индивидуально описано во втором случае.
  3. создать экземпляр и установить стандарт SecurityManager.
  4. создать ProtectionDomain подкласс, способный хранить и выставлять SNAAs.
  5. автор1 a DomainCombiner это

    1. строится с помощью SNAAs;
    2. осуществляет combine(ProtectionDomain[], ProtectionDomain[]) такое, что

      1. он заменяет Домены аргумента первого ("текущего" контекста) массива эквивалентными экземплярами пользовательской реализации;
      2. затем добавляет второй ("назначенный "или" унаследованный " контекст) аргумент, если таковой имеется, к первому как есть; и, наконец,
      3. возвращает конкатенацию.

    как Policy::implies реализация должна быть эффективной (например, путем устранения повторений), так как он будет вызывается каждый раз, когда getContext и checkPermissionAccessController методы.

  6. после успешной аутентификации создайте новый AccessControlContext который обертывает текущий, вместе с экземпляром custom DomainCombiner, в свою очередь оборачивая СНС. Оберните код, который будет выполняться за пределами ссылки "в" в AccessController::doPrivilegedWithCombiner вызов, также проходящий вдоль контекста управления доступом замены.

1 вместо того, чтобы использовать пользовательские домены и свой собственный реализация объединителя, есть также, казалось бы, более простая альтернатива перевода SNAAs в Principals и, используя стандарт SubjectDomainCombiner, привязывая их к текущему AccessControlContextдомены (как указано выше, или просто через Subject::doAs). Снижает ли этот подход эффективность политики, зависит в первую очередь от глубины стека вызовов (сколько различных доменов содержит контекст управления доступом). В конце концов оптимизации кэширования вы думали, что вы могли бы избежать реализации как часть домена combiner ударит вас назад при создании политики, так что это по существу дизайнерское решение, которое вы должны будете сделать в этот момент.