User Tools

Site Tools


java_security

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
java_security [2007/02/09 12:08] slonopotamusjava_security [2007/04/10 10:39] slonopotamus
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 
java_security.txt · Last modified: 2019/06/12 16:08 by 127.0.0.1