User Tools

Site Tools


java_security

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

java_security [2007/02/09 12:24]
slonopotamus
java_security [2019/06/12 16:08]
Line 1: Line 1:
-[[start|На главную]] 
  
-====== Реализация системы безопасности в Java ====== 
-  Всё нижеописанное исходит из предположения что в Sun хорошо подумали когда 
-  проектировали пермишены,​ секьюрити-менеджер и всё с ними связанное. 
- 
- 
-===== О чём это вообще ===== 
-В типичном веб-приложении далеко не каждый пользователь может менять любые данные. У кого-то есть доступ только на чтение,​ кто-то может менять только свои данные,​ кто-то только данные пользователей из определённой группы или находящиеся в определённом состоянии. Возникает задача разграничивания прав. Есть несколько вариантов её решения. Вариант первый - логика разрешения/​запрещения жёстко задаётся в коде. Существует жёстко заданный набор групп с наборами правам. Этот подход работает только до тех пор пока не возникает необходимости изменить эти наборы. Другой подход связан с динамическим созданием групп и динамическим же назначением им прав. И логика по проверке просто проверяет,​ есть ли у текущего пользователя право на то действие,​ которое он пытается совершить. 
-==== Что защищать ==== 
-Любые данные. 
-==== Зачем защищать ==== 
-Чтобы разделять,​ кому что можно, а кому что нельзя делать. 
- 
- 
-===== Аутентификация ===== 
-==== Несортированный трэш ==== 
-<code java> 
-    //​Authorization init 
-    Policy.setPolicy(new Policy() 
-    { 
-      public boolean implies(final ProtectionDomain domain, final Permission permission) 
-      { 
-        for (final Principal principal : domain.getPrincipals()) { 
-          if (principal instanceof MyPrincipal) { 
-            //​получить откуда-то коллекцию прав принципала и вызвать для них implies, передав в качестве аргумента проверяемый пермишен. 
-          } 
-        } 
-        return false; 
-      } 
-    }); 
-    //​Authentication init 
-    final Configuration orig = Configuration.getConfiguration();​ 
-    Configuration.setConfiguration(new Configuration() 
-    { 
-      public AppConfigurationEntry[] getAppConfigurationEntry(final String name) 
-      { 
-        return (name.equals("​MY_APP"​)) ? 
-            new AppConfigurationEntry[]{ 
-                new AppConfigurationEntry( 
-                    "​com.myApp.security.MyLoginModule",​ //наша реализация LoginModule. 
-                    AppConfigurationEntry.LoginModuleControlFlag.REQUISITE,​ 
-                    Collections.<​String,​ Object>​emptyMap() 
-                ) 
-            } : orig.getAppConfigurationEntry(name);​ 
-      } 
- 
-      public void refresh() 
-      { 
-        orig.refresh();​ 
-      } 
-    }); 
-    System.setSecurityManager(new SecurityManager());​ 
-    //​Аутентификация 
-    final String name = "​login";​ 
-    final String password = "​password";​ 
-    final LoginContext ctx = new LoginContext("​MY_APP",​ new CallbackHandler() 
-    { 
-      public void handle(final Callback[] callbacks) throws IOException,​ UnsupportedCallbackException 
-      { 
-        for (final Callback cb : callbacks) 
-        { 
-          if (cb instanceof NameCallback) 
-          { 
-            ((NameCallback) cb).setName(name);​ 
-          } 
-          else if (cb instanceof PasswordCallback) 
-          { 
-            ((PasswordCallback) cb).setPassword(password.toCharArray());​ 
-          } 
-          else 
-          { 
-            throw new UnsupportedCallbackException(cb);​ 
-          } 
-        } 
-      } 
-    }); 
-    ctx.login();​ 
-    //​выполнение кода в контексте аутентифицированного пользователя 
-    Subject.doAs(ctx.getSubject(),​ new PrivilegedAction<​Object>​() 
-    { 
-      public Object run() 
-      { 
-        //Do something 
-        return null; 
-      } 
-    }); 
-    ctx.logout();​ 
-</​code>​ 
- 
-===== Авторизация ===== 
- 
-==== Краткое описание проверки пермишена ==== 
-В Java существует [[http://​java.sun.com/​j2se/​1.5.0/​docs/​guide/​security/​spec/​security-specTOC.fm.html|встроенный механизм прав]]. 
- 
-  * Проверяется,​ не равен ли ''​null'''​у ''​System#​getSecurityManager()''​. 
-    * Если равен, то считается что действие разрешено делать. 
-  * Вызывается [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​lang/​SecurityManager.html#​checkPermission(java.security.Permission)|SecurityManager#​checkPermission(java.security.Permission)]] 
-  * Берётся текущий ''​AccessControlContext''​ и вызывается у него метод [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​AccessControlContext.html#​checkPermission(java.security.Permission)|AccessControlContext#​checkPermission(java.security.Permission)]] 
-  * ''​AccessControlContext''​ итерейтится по содержащимся в нём ''​ProtectionDomain'''​ам и у них вызывается метод [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​ProtectionDomain.html#​implies(java.security.Permission)|ProtectionDomain#​implies(java.security.Permission)]] 
-  * Берётся текущая ''​Policy'',​ у которой вызывается метод [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​Policy.html#​implies(java.security.ProtectionDomain,​ java.security.Permission)|Policy#​implies(java.security.ProtectionDomain,​ java.security.Permission)]] с данным ''​ProtectionDomain''​ом. 
- 
-==== Компоненты системы авторизации ==== 
- 
-  * [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​lang/​SecurityManager.html|SecurityManager]] - просто фасад над всей системой прав. 
-  * [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​AccessControlContext.html|AccessControlContext]] - контекст с информацией о том, в каких ''​ProtectionDomain'''​ах выполняется сейчас код. 
-  * [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​ProtectionDomain.html|ProtectionDomain]] - содержит информацию об URL'​ах (возможно с сертификатами),​ из которых получен выполняющийся код, ''​ClassLoader'',​ через который этот код был получен и (**внимание**) коллекцию [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​Principal.html|Principal]]'​ов,​ от имени которых код выполняется. 
-  * [[http://​java.sun.com/​j2se/​1.5.0/​docs/​api/​java/​security/​Policy.html|Policy]] - хранилище пермишенов,​ которое определяет какие права у кого есть. 
- 
- 
-==== Внедрение своих правил авторизации ==== 
- 
- 
-=== Principal === 
- 
-Скорее всего у вас в приложении есть класс ''​User''​. Нужно будет написать реализацию ''​Principal'''​а для него (Внимание! Не надо делать так чтобы ваш ''​User''​ реализовывал ''​Principal'''​а,​ т.к. отсутствие юзера не означает отсутствие ''​Principal'''​а). 
- 
-== Примерная реализация == 
-<code java> 
-public class UserPrincipal implements java.security.Principal { 
-  // ------------------------------ FIELDS ------------------------------ 
-  /** 
-   * Константа для незарегистрированного пользователя. 
-   */ 
-  private static final UserPrincipal nullUserPrincipal = new UserPrincipal (null); 
-  private final User user; 
- 
-  // -------------------------- STATIC METHODS -------------------------- 
- 
-  public static UserPrincipal getPrincipal (final User user) { 
-    return user == null ? nullUserPrincipal : new UserPrincipal (user); 
-  } 
- 
-  // --------------------------- CONSTRUCTORS --------------------------- 
- 
-  protected UserPrincipal (final User user) { 
-    super (); 
-    this.user = user; 
-  } 
- 
-  // ------------------------ CANONICAL METHODS ------------------------ 
- 
-  public boolean equals (final Object obj) { 
-    if (obj == null || !(obj instanceof UserPrincipal)) { 
-      return false; 
-    } 
-    final UserPrincipal o = (UserPrincipal) obj; 
-    final User myUser = this.getUser (); 
-    final User oUser = o.getUser (); 
-    if (myUser == null && oUser == null) { 
-      return true; 
-    } else if (myUser != null && oUser != null) { 
-      return myUser.equals (oUser); 
-    } else { 
-      return false; 
-    } 
-  } 
- 
-  public int hashCode () { 
-    return this.getClass ().hashCode () + (this.user == null ? 13 : this.user.hashCode ()); 
-  } 
- 
-  // ------------------------ INTERFACE METHODS ------------------------ 
- 
-  // --------------------- Interface Nullable --------------------- 
- 
-  public boolean isNull () { 
-    return this.user == null; 
-  } 
- 
-  // --------------------- Interface Principal --------------------- 
- 
-  public String getName () { 
-    return this.getClass ().getName () + " " + (this.user == null ? "​unregistered"​ : this.getUser ().getUserId ()); 
-  } 
- 
-  // -------------------------- OTHER METHODS -------------------------- 
- 
-  public User getUser () { 
-    return this.user; 
-  } 
-} 
-</​code>​ 
- 
- 
-=== Policy === 
-''​Policy''​ - это как раз то, куда надо всовывать свой код, чтобы делать проверку прав по своей базе, а не по стандартной реализации в policy-файле. Делается это просто - пишется свой класс, наследующийся от ''​Policy''​ (внимание,​ если в вашем приложении права могут динамически изменяться,​ то надо переопределять метод ''​implies'',​ т.к. в стандартной реализации он активно занимается кэшированием пермишенов. 
- 
-> **ВНИМАНИЕ** Считается,​ что право разрешено,​ если оно разрешено для **ВСЕХ** ProtectionDomain'​ов,​ находящихся в ''​AccessControlContext'''​е вызывающего кода. 
- 
- 
- 
-=== Собираем вместе === 
- 
-== Установка Policy == 
-<code java> 
-Policy.setPolicy (new MyPolicy ()); 
-</​code>​ 
- 
-== Включение SecurityManager'​а == 
-<code java> 
-if (System.getSecurityManager () != null) { 
-  System.setSecurityManager (new SecurityManager ()); 
-} 
-</​code>​ 
- 
-== Вызов защищённого кода == 
-<code java> 
-try { 
-  final Subject subject = ...; 
-  final T result = Subject.doAs (subject, new PrivilegedExceptionAction<​T>​() { 
-    public Object run () throws IOException,​ ServletException { 
-      //​выполнить какой-то код, защищённый правами. 
-    } 
-  }); 
-} catch (PrivilegedActionException e) { 
-  ... 
-} 
-</​code>​ 
- 
-== SecurityUtils == 
-Пара методов для удобства. 
- 
-<code java> 
-public final class SecurityUtils { 
-  public static boolean hasPermission (final Permission permission) { 
-    try { 
-      checkPermission (permission);​ 
-      return true; 
-    } catch (final SecurityException e) { 
-      return false; 
-    } 
-  } 
- 
-  public static void checkPermission (final Permission permission) throws SecurityException { 
-    if (System.getSecurityManager () != null) { 
-      System.getSecurityManager ().checkPermission (permission);​ 
-    } 
-  } 
-} 
-</​code>​ 
- 
- 
-===== Альтернативы ===== 
-  * [[http://​acegisecurity.org/​|Acegi Security]] 
-FIXME 
- 
-===== Permissions Evangelizm ===== 
-FIXME 
- 
-====== JAAS vs Acegi Security ====== 
- 
-===== Java Security (JAAS) ===== 
-{{jsf-ru:​plus.gif}} Является стандартом,​ поддерживается большим количеством технологий (EJB, Servlets, etc) 
- 
-{{jsf-ru:​plus.gif}} Простой API 
- 
-{{jsf-ru:​plus.gif}} Хорошо документирован 
- 
-{{jsf-ru:​minus.gif}} Довольно скудная базовая функциональность 
- 
-{{jsf-ru:​minus.gif}} Ограниченное встроенное кэширование (не предполагает изменения набора прав в процессе работы приложения),​ в случае отключения которого необходимо реализовывать кэширование на уровне приложения 
- 
-{{jsf-ru:​minus.gif}} Отсутствуют теги для проверки прав к различным элементам интерфейса (однако возможно их написание) 
- 
-{{jsf-ru:​minus.gif}} Политики принятия решений необходимо реализовывать вручную 
- 
-{{jsf-ru:​minus.gif}} В некоторых случаях контейнеро-зависим (однако возможно написание контейнеро-независимого кода) 
- 
- 
-===== Acegi Security ===== 
- 
-{{jsf-ru:​plus.gif}} Хорошо документирован 
- 
-{{jsf-ru:​plus.gif}} Простая интеграция со Spring 
- 
-{{jsf-ru:​plus.gif}} Встроенные аудиты 
- 
-{{jsf-ru:​plus.gif}} Встроенные интерцепторы (например,​ для удаления из коллекций недоступных объектов) 
- 
-{{jsf-ru:​plus.gif}} Различные политики принятия решений (если все полиси разрешают,​ если хоть одна полиси разрешает,​ на основе голосования и очков) 
- 
-{{jsf-ru:​plus.gif}} Встроенные теги для проверки прав к различным элементам интерфейса (правда примитивные) 
- 
-{{jsf-ru:​plus.gif}} Встроенное кэширование 
- 
-{{jsf-ru:​plus.gif}} Контейнеро-независим 
- 
-{{jsf-ru:​plus.gif}} Встроенная поддержка опции «запомнить меня» 
- 
-{{jsf-ru:​minus.gif}} Многократно более сложный API 
- 
-{{jsf-ru:​minus.gif}} Не специфицирован 
- 
-При этом следует учитывать,​ что имеется возможность оборачивать использование сторонним кодом JAAS’а в обращения к Acegi и наоборот. Так же необходимо понимать,​ что права виртуальной машины (доступ к файлам,​ сокетам,​ работа с класслоадерами и т.д. проверяются через JAAS, поэтому при использовании Acegi в любом случае будет необходимо направлять в него обращения к JAAS). 
java_security.txt · Last modified: 2019/06/12 16:08 (external edit)