2017-10-22 21:38:47 +0000   |     java security manager permission   |   Viewed times   |    

前言

简单介绍Java安全管理器框架。看看SecurityManager,Permission,ProtectionDomain,CodeSource,Policy这些类是怎么一起工作的。

权限Permission类是安全管理的核心

权限Permission封装了特定权限的详细信息。就是由一组字符串定义的。比如下面的的例子,FilePermission的实例定义了一条具体权限:在/tmp/目录下的读写任何文件的权限。

FilePermission p = new FilePermission("/tmp/*", "read,write");

Permission是怎么工作的?

Permission最重要的就是implies()函数。是定义权限规则的地方。它要配合SecurityManager#checkPermission(Permission)函数工作。官方的解释如下,

Checks if the specified permission’s actions are “implied by” this object’s actions.

比如下面的例子,我定义了一个WordCheckPermission,然后badWordSet()函数里定义了一组不合法的单词集合。比如说fuck,sex,bitch是不合法的。然后在implies()函数的伪代码是:

如果传进来的Permission的name字段是这些不合法的单词就返回false。

import java.security.*;
import java.util.*;

/**
 * A permission that checks for bad words.
 * @version 1.00 1999-10-23
 * @author Cay Horstmann
 */
public class WordCheckPermission extends Permission {
    /**
     * Constructs a word check permission
     * @param target a comma separated word list
     * @param anAction "insert" or "avoid"
     */
    public WordCheckPermission(String target, String anAction) {
       super(target);
       action = anAction;
    }

    public String getActions() {
       return action;
    }

    public boolean equals(Object other) {
       if (other == null) return false;
       if (!getClass().equals(other.getClass())) {
         return false;
       }
       WordCheckPermission b = (WordCheckPermission) other;
       if (!action.equals(b.action)) {
         return false;
       }
       if (action.equals("insert")) {
         return getName().equals(b.getName());
       }
       else if (action.equals("avoid")) {
         return badWordSet().equals(b.badWordSet());
       } else {
         return false;
       }
    }

    public int hashCode() {
       return getName().hashCode() + action.hashCode();
    }

    /**
     * Permission关键就是这个implies函数:
     *     它定义了参数传进来的Permission对象是否 “符合” 当前Permission对象定义的权限
     */
    public boolean implies(Permission other) {
       if (!(other instanceof WordCheckPermission)) {
           return false;
       }
       WordCheckPermission b = (WordCheckPermission) other;
       if (action.equals("insert")) {
          return b.action.equals("insert") && getName().indexOf(b.getName()) >= 0;
       } else if (action.equals("avoid")) {
          if (b.action.equals("avoid")) {
              return b.badWordSet().containsAll(badWordSet());
          } else if (b.action.equals("insert")) {
             for (String badWord : badWordSet()) {
                if (b.getName().indexOf(badWord) >= 0) { return false; }
             }
             return true;
          } else {
              return false;
          }
       } else {
           return false;
       }
    }

    /**
     * Gets the bad words that this permission rule describes.
     * @return a set of the bad words
     */
    public Set<String> badWordSet() {
       Set<String> set = new HashSet<String>();
       set.addAll(Arrays.asList(getName().split(",")));
       return set;
    }

    private String action;
}

然后我再append()函数里,真正执行super.append()之前,都执行checkPermission()检查,只有通过了才添加这个单词。就可以做到敏感词过滤的作用。

public void append(String text) {
   WordCheckPermission p = new WordCheckPermission(text, "insert");
   SecurityManager manager = System.getSecurityManager();
   if (manager != null) manager.checkPermission(p);  // !关键的权限检查在这里
   super.append(text);
}

一般的使用场景是:每个类都有一个ProtectionDomain,其中封装了一系列的CodeSourcePermission集合。通过这一系列的规则定义某个类的安全规则。

ProtectionDomain(CodeSource codesource, PermissionCollection permissions)

详细内容,参见下面《Java核心技术》对安全管理器的表述

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18