前言
月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂)
央是一片海洋,海乃百川,代表着一块海绵(吸纳万物)
泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出)
月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容
希望大家一起坚持这个过程,也同样希望大家最终都能从零到零,把知识从薄变厚,再由厚变薄!
一.SecurityManage的作用:
直接看源码注释(我的翻译可能不太准,如果道友们有更棒的理解,可以留言或者私信)
/**
* The security manager is a class that allows
* applications to implement a security policy. It allows an
* application to determine, before performing a possibly unsafe or
* sensitive operation, what the operation is and whether
* it is being attempted in a security context that allows the
* operation to be performed. The
* application can allow or disallow the operation.
* 1.安全管理器是一个允许应用程序实现安全策略的类。
* 它允许应用程序在执行可能不安全或敏感的操作之前确定该操作是什么以及是否正在允许执行该操作的安全上下文中尝试该操作。
* 应用程序可以允许或禁止该操作
* <p>
* The <code>SecurityManager</code> class contains many methods with
* names that begin with the word <code>check</code>. These methods
* are called by various methods in the Java libraries before those
* methods perform certain potentially sensitive operations. The
* invocation of such a <code>check</code> method typically looks like this:
* <blockquote><pre>
* SecurityManager security = System.getSecurityManager();
* if (security != null) {
* security.check<i>XXX</i>(argument, . . . );
* }
* </pre></blockquote>
* <p>
* 2.SecurityManager类包含许多名称以单词check开头的方法。在 Java 库中的各种方法执行某些可能敏感的操作之前,
* 这些方法会调用这些方法。此类check方法的调用通常如下所示:
* SecurityManager security = System.getSecurityManager();
* * if (security != null) {
* * security.checkXXX(argument, . . . );
* * }
* The security manager is thereby given an opportunity to prevent
* completion of the operation by throwing an exception. A security
* manager routine simply returns if the operation is permitted, but
* throws a <code>SecurityException</code> if the operation is not
* permitted. The only exception to this convention is
* <code>checkTopLevelWindow</code>, which returns a
* <code>boolean</code> value.
* 3.因此,安全管理器有机会通过抛出异常来阻止操作的完成。如果操作被允许,安全管理器例程简单地返回,
* 但如果操作不被允许,则抛出SecurityException。此约定的唯一例外是 checkTopLevelWindow,它返回一个boolean 值。
* <p>
* The current security manager is set by the
* <code>setSecurityManager</code> method in class
* <code>System</code>. The current security manager is obtained
* by the <code>getSecurityManager</code> method.
* 4.当前安全管理器由System类中的setSecurityManager方法设置。当前的安全管理器通过getSecurityManager方法获得。
* <p>
* The special method
* {@link SecurityManager#checkPermission(java.security.Permission)}
* determines whether an access request indicated by a specified
* permission should be granted or denied. The
* default implementation calls
*
* <pre>
* AccessController.checkPermission(perm);
* </pre>
* 5.特殊方法SecurityManager.checkPermission(java.security.Permission)确定是否应授予或拒绝指定权限指示的访问请求。
* 默认实现调用 AccessController.checkPermission(perm);
* <p>
* If a requested access is allowed,
* <code>checkPermission</code> returns quietly. If denied, a
* <code>SecurityException</code> is thrown.
* 6.如果允许请求的访问,checkPermission安静地返回。如果被拒绝,则抛出SecurityException
* <p>
* As of Java 2 SDK v1.2, the default implementation of each of the other
* <code>check</code> methods in <code>SecurityManager</code> is to
* call the <code>SecurityManager checkPermission</code> method
* to determine if the calling thread has permission to perform the requested
* operation.
* 7.从 Java 2 SDK v1.2 开始,SecurityManager中其他每个check方法的默认实现
* 是调用SecurityManager checkPermission 方法来确定调用线程有权执行请求的操作
* <p>
* Note that the <code>checkPermission</code> method with
* just a single permission argument always performs security checks
* within the context of the currently executing thread.
* Sometimes a security check that should be made within a given context
* will actually need to be done from within a
* <i>different</i> context (for example, from within a worker thread).
* The {@link SecurityManager#getSecurityContext getSecurityContext} method
* and the {@link SecurityManager#checkPermission(java.security.Permission,
* java.lang.Object) checkPermission}
* method that includes a context argument are provided
* for this situation. The
* <code>getSecurityContext</code> method returns a "snapshot"
* of the current calling context. (The default implementation
* returns an AccessControlContext object.) A sample call is
* the following:
* 8.请注意,只有一个权限参数的checkPermission方法始终在当前执行的线程的上下文中执行安全检查。
* 有时,应该在给定上下文中进行的安全检查实际上需要在不同的上下文中完成(例如,从工作线程中)。
* 针对这种情况提供了 SecurityManager.getSecurityContext方法和包含上下文参数的
* SecurityManager.checkPermission(java.security.Permission, java.lang.Object) checkPermission} 方法。
* <pre>
* Object context = null;
* SecurityManager sm = System.getSecurityManager();
* if (sm != null) context = sm.getSecurityContext();
* </pre>
*9.getSecurityContext方法返回当前调用上下文的“快照”。 (默认实现返回一个 AccessControlContext 对象。)示例调用如下:
* Object context = null;
* SecurityManager sm = System.getSecurityManager();
* if (sm != null) context = sm.getSecurityContext();
* <p>
* The <code>checkPermission</code> method
* that takes a context object in addition to a permission
* makes access decisions based on that context,
* rather than on that of the current execution thread.
* Code within a different context can thus call that method,
* passing the permission and the
* previously-saved context object. A sample call, using the
* SecurityManager <code>sm</code> obtained as in the previous example,
* is the following:
*
* <pre>
* if (sm != null) sm.checkPermission(permission, context);
* </pre>
* 10.除了权限之外,还采用上下文对象的 checkPermission方法根据该上下文而不是当前执行线程的上下文做出访问决策。
* 因此,不同上下文中的代码可以调用该方法,传递权限和先前保存的上下文对象。使用如上例中获得的 SecurityManager sm 的示例调用如下:
*if (sm != null) sm.checkPermission(permission, context);
* <p>Permissions fall into these categories: File, Socket, Net,
* Security, Runtime, Property, AWT, Reflect, and Serializable.
* The classes managing these various
* permission categories are <code>java.io.FilePermission</code>,
* <code>java.net.SocketPermission</code>,
* <code>java.net.NetPermission</code>,
* <code>java.security.SecurityPermission</code>,
* <code>java.lang.RuntimePermission</code>,
* <code>java.util.PropertyPermission</code>,
* <code>java.awt.AWTPermission</code>,
* <code>java.lang.reflect.ReflectPermission</code>, and
* <code>java.io.SerializablePermission</code>.
*11.权限分为以下几类:文件、套接字、网络、安全、运行时、属性、AWT、反射和可序列化
* <p>All but the first two (FilePermission and SocketPermission) are
* subclasses of <code>java.security.BasicPermission</code>, which itself
* is an abstract subclass of the
* top-level class for permissions, which is
* <code>java.security.Permission</code>. BasicPermission defines the
* functionality needed for all permissions that contain a name
* that follows the hierarchical property naming convention
* (for example, "exitVM", "setFactory", "queuePrintJob", etc).
* 12.除了前两个(FilePermission 和 SocketPermission)都是java.security.BasicPermission的子类,
* 它本身是顶级权限类的抽象子类,它是 java.security.Permission。
* BasicPermission 定义包含遵循分层属性命名约定的名称的所有权限所需的功能(例如,“exitVM”、“setFactory”、“queuePrintJob”等)
* An asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. For example: "a.*" or "*" is valid,
* "*a" or "a*b" is not valid.
* 13.星号可能出现在名称的末尾,跟在“.”之后,或者单独出现,以表示通配符匹配。例如:“a.*”。或“*”有效,“*a”或“a*b”无效
* <p>FilePermission and SocketPermission are subclasses of the
* top-level class for permissions
* (<code>java.security.Permission</code>). Classes like these
* that have a more complicated name syntax than that used by
* BasicPermission subclass directly from Permission rather than from
* BasicPermission. For example,
* for a <code>java.io.FilePermission</code> object, the permission name is
* the path name of a file (or directory).
* 14.FilePermission 和 SocketPermission 是顶级权限类 (java.security.Permission) 的子类。
* 像这样的类具有比 BasicPermission 子类直接来自 Permission 而不是来自 BasicPermission 的名称语法更复杂的名称语法。
* 例如,对于 java.io.FilePermission对象,权限名称是文件(或目录)的路径名
* <p>Some of the permission classes have an "actions" list that tells
* the actions that are permitted for the object. For example,
* for a <code>java.io.FilePermission</code> object, the actions list
* (such as "read, write") specifies which actions are granted for the
* specified file (or for files in the specified directory).
* 15.一些权限类有一个“动作”列表,它告诉对象允许的动作。例如,对于java.io.FilePermission对象,
* 操作列表(例如“读取、写入”)指定为指定文件(或指定目录中的文件)授予哪些操作。
* <p>Other permission classes are for "named" permissions -
* ones that contain a name but no actions list; you either have the
* named permission or you don't.
* 16.其他权限类用于“命名”权限 - 包含名称但没有操作列表的权限;您要么拥有指定权限,要么没有。
* <p>Note: There is also a <code>java.security.AllPermission</code>
* permission that implies all permissions. It exists to simplify the work
* of system administrators who might need to perform multiple
* tasks that require all (or numerous) permissions.
* 17.注意:还有一个 java.security.AllPermission权限表示所有权限。
* 它的存在是为了简化系统管理员的工作,他们可能需要执行需要所有(或多个)权限的多项任务
* <p>
* See <a href ="../../../technotes/guides/security/permissions.html">
* Permissions in the JDK</a> for permission-related information.
* This document includes, for example, a table listing the various SecurityManager
* <code>check</code> methods and the permission(s) the default
* implementation of each such method requires.
* It also contains a table of all the version 1.2 methods
* that require permissions, and for each such method tells
* which permission it requires.
* 18.有关权限相关信息,请参阅<a href ="......technotesguidessecuritypermissions.html"> JDK 中的权限<a>。
* 例如,该文档包括一个表格,其中列出了各种 SecurityManager.check方法以及每个此类方法的默认实现所需的权限。
* 它还包含需要权限的所有版本 1.2 方法的表,并且对于每个这样的方法说明它需要哪种权限
* <p>
* For more information about <code>SecurityManager</code> changes made in
* the JDK and advice regarding porting of 1.1-style security managers,
* see the <a href="../../../technotes/guides/security/index.html">security documentation</a>.
* 19.有关SecurityManager在 JDK 中所做更改的更多信息以及有关移植 1.1 样式安全管理器的建议,
* 请参阅<a href="......technotesguidessecurityindex.html">安全文档
*
* @since JDK1.0
*/
二.成员变量:
/*
* 1.对于类变量,我们有一个初始无效位(初始为假),用于判断缓存是否有效。
* 如果底层 java.security.Security 属性通过 setProperty() 更改,
* 则 Security 类使用反射来更改变量,从而使缓存无效
* 2.锁定是通过同步到 packageAccessLock.packageDefinitionLock 对象来处理的。它们只在这个类中使用
* 3.请注意,由于属性更改而导致的缓存失效在不使用这些锁的情况下发生,因此线程更新属性与其他线程更新缓存之间可能存在延迟。
*/
private static boolean packageAccessValid = false;
private static String[] packageAccess;
private static final Object packageAccessLock = new Object();
private static boolean packageDefinitionValid = false;
private static String[] packageDefinition;
private static final Object packageDefinitionLock = new Object();
/**
* 如果正在进行安全检查,则此字段为true; false否则
*/
@Deprecated
protected boolean inCheck;
/*
* Have we been initialized. Effective against finalizer attacks.
* 我们有没有被初始化。有效对抗终结器攻击。
*/
private boolean initialized = false;
/**
* 对根线程组的引用,用于 checkAccess 方法
*/
private static ThreadGroup rootGroup = getRootGroup();
三.构造方法:
/**
* 1.构造一个新的 SecurityManager
* 2.如果已经安装了安全管理器,该方法首先调用安全管理器的checkPermission方法,
* 并具有RuntimePermission("createSecurityManager")权限,以确保调用线程有权创建新的安全经理
* 3.这可能会导致抛出SecurityException
*/
public SecurityManager() {
synchronized(SecurityManager.class) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// ask the currently installed security manager if we
// can create a new one.
//询问当前安装的安全管理器是否可以创建一个新的安全管理器。
sm.checkPermission(new RuntimePermission
("createSecurityManager"));
}
initialized = true;
}
}
四.内部方法:
getSecurityContext
/**
* 1.创建一个封装当前执行环境的对象。例如,该方法的结果由三参数checkConnect方法和两参数checkRead方法使用
* 2.需要这些方法是因为可能会调用受信任的方法来代表另一个方法读取文件或打开套接字。
* 受信任的方法需要确定是否允许其他(可能不受信任的)方法自行执行操作。
* 3.此方法的默认实现是返回一个AccessControlContext对象。
*/
public Object getSecurityContext() {
return AccessController.getContext();
}
checkPermission
/**
* 1.如果基于当前有效的安全策略不允许由给定权限指定的请求访问,则抛出SecurityException。
* 2.此方法使用给定的权限调用AccessController.checkPermission
*/
public void checkPermission(Permission perm) {
java.security.AccessController.checkPermission(perm);
}
checkPermission
/**
* 1.如果指定的安全上下文被拒绝访问由给定权限指定的资源,则抛出SecurityException。
* 上下文必须是先前调用 getSecurityContext返回的安全上下文,并且访问控制决策基于为该安全上下文配置的安全策略。
* 2.如果context是AccessControlContext的实例,则使用指定的权限调用AccessControlContext.checkPermission方法。
* 3.如果context不是AccessControlContext的实例,则抛出SecurityException。
*/
public void checkPermission(Permission perm, Object context) {
if (context instanceof AccessControlContext) {
((AccessControlContext)context).checkPermission(perm);
} else {
throw new SecurityException();
}
}
checkCreateClassLoader
/**
* 1.如果不允许调用线程创建新的类加载器,则抛出SecurityException。
* 2.此方法使用RuntimePermission("createClassLoader")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用 super.checkCreateClassLoader
*/
public void checkCreateClassLoader() {
checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
}
检测各种...
/**
* 1.如果不允许调用线程修改线程参数,则抛出SecurityException
* <p>
* 2.此方法由 stop, suspend,resume,setPriority, setName为当前安全管理器调用
* 和 setDaemon类的方法 Thread
* 3.如果线程参数是系统线程(属于具有 null父级的线程组),
* 则此方法使用RuntimePermission("modifyThread")调用checkPermission<允许。
* 如果 thread 参数不是系统线程,则此方法只是静默返回。
* 4.需要更严格策略的应用程序应覆盖此方法。如果此方法被覆盖,
* 则覆盖它的方法还应检查调用线程是否具有RuntimePermission("modifyThread")权限,
* 如果是,则静默返回。这是为了确保授予该权限的代码(例如 JDK 本身)可以操作任何线程。
* 5.如果这个方法被覆盖,那么super.checkAccess应该被覆盖方法中的第一条语句调用,
* 或者等效的安全检查应该放在被覆盖的方法中
*/
public void checkAccess(Thread t) {
if (t == null) {
throw new NullPointerException("thread can't be null");
}
if (t.getThreadGroup() == rootGroup) {
checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION);
} else {
// just return
}
}
/**
* 1.如果不允许调用线程修改线程组参数,则抛出 SecurityException。
* 2.当创建新的子线程或子线程组时,为当前安全管理器调用此方法,
* 并通过 setDaemon, setMaxPriority, stop, ThreadGroup类的suspend、resume和destroy方法。
* 3.如果线程组参数是系统线程组(具有null父级),则此方法使用RuntimePermission("modifyThreadGroup")
* 权限调用checkPermission。如果线程组参数不系统线程组,则此方法仅静默返回。
* 4.需要更严格策略的应用程序应覆盖此方法。如果此方法被覆盖,则覆盖它的方法还应检查调用线程
* 是否具有RuntimePermission("modifyThreadGroup")权限,如果是,则静默返回。
* 这是为了确保授予该权限的代码(例如 JDK 本身)可以操作任何线程
* 5.如果这个方法被覆盖,那么super.checkAccess应该被覆盖方法中的第一条语句调用,
* 或者等效的安全检查应该放在被覆盖的方法中。
*/
public void checkAccess(ThreadGroup g) {
if (g == null) {
throw new NullPointerException("thread group can't be null");
}
if (g == rootGroup) {
checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
} else {
// just return
}
}
/**
* 1.如果不允许调用线程导致 Java 虚拟机以指定的状态代码暂停,则抛出SecurityException
* 2.该方法由Runtime类的exit方法为当前安全管理器调用。0的状态表示成功;其他值表示各种错误
* 3.此方法使用RuntimePermission("exitVM."+status)权限调用checkPermission。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkExit。
*/
public void checkExit(int status) {
checkPermission(new RuntimePermission("exitVM."+status));
}
/**
* 1.如果不允许调用线程创建子进程,则抛出SecurityException。
* 2.该方法由Runtime类的exec方法为当前安全管理器调用。
* 3.如果 cmd 是绝对路径,则此方法使用FilePermission(cmd,"execute")权限调用checkPermission,
* 否则调用checkPermission和FilePermission( "<<所有文件>>","执行")<代码>。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkExec
*/
public void checkExec(String cmd) {
File f = new File(cmd);
if (f.isAbsolute()) {
checkPermission(new FilePermission(cmd,
SecurityConstants.FILE_EXECUTE_ACTION));
} else {
checkPermission(new FilePermission("<<ALL FILES>>",
SecurityConstants.FILE_EXECUTE_ACTION));
}
}
/**
* 1.如果不允许调用线程动态链接由字符串参数文件指定的库代码,则抛出SecurityException。
* 参数是一个简单的库名或一个完整的文件名。
* 2.此方法由类Runtime 的方法load和loadLibrary为当前安全管理器调用。.
* 3.此方法使用RuntimePermission("loadLibrary."+lib)权限调用checkPermission
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkLink
*/
public void checkLink(String lib) {
if (lib == null) {
throw new NullPointerException("library can't be null");
}
checkPermission(new RuntimePermission("loadLibrary."+lib));
}
/**
* 1.如果不允许调用线程从指定的文件描述符中读取,则抛出SecurityException
* 2.此方法使用RuntimePermission("readFileDescriptor")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkRead
*/
public void checkRead(FileDescriptor fd) {
if (fd == null) {
throw new NullPointerException("file descriptor can't be null");
}
checkPermission(new RuntimePermission("readFileDescriptor"));
}
/**
* 1.如果不允许调用线程读取由字符串参数指定的文件,则抛出SecurityException。
* 2.此方法使用FilePermission(file,"read")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkRead
*/
public void checkRead(String file) {
checkPermission(new FilePermission(file,
SecurityConstants.FILE_READ_ACTION));
}
/**
* 1.如果不允许指定的安全上下文读取由字符串参数指定的文件,则抛出SecurityException。
* 上下文必须是先前调用getSecurityContext返回的安全上下文。如果context是AccessControlContext的一个实例,
* 那么AccessControlContext.checkPermission方法将使用FilePermission(file,"read") 调用权限。
* 如果context不是AccessControlContext的实例,则抛出SecurityException
* 2.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用 super.checkRead
*/
public void checkRead(String file, Object context) {
checkPermission(
new FilePermission(file, SecurityConstants.FILE_READ_ACTION),
context);
}
/**
* 1.如果不允许调用线程写入指定的文件描述符,则抛出SecurityException
* 2.此方法使用RuntimePermission("writeFileDescriptor")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkWrite
*/
public void checkWrite(FileDescriptor fd) {
if (fd == null) {
throw new NullPointerException("file descriptor can't be null");
}
checkPermission(new RuntimePermission("writeFileDescriptor"));
}
/**
* 1.如果不允许调用线程写入由字符串参数指定的文件,则抛出SecurityException。
* 2.此方法使用FilePermission(file,"write")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkWrite
*/
public void checkWrite(String file) {
checkPermission(new FilePermission(file,
SecurityConstants.FILE_WRITE_ACTION));
}
/**
* 1.如果不允许调用线程删除指定的文件,则抛出SecurityException。
* 2.该方法由File类的delete方法为当前安全管理器调用
* 3.此方法使用FilePermission(file,"delete")权限调用checkPermission。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkDelete
*/
public void checkDelete(String file) {
checkPermission(new FilePermission(file,
SecurityConstants.FILE_DELETE_ACTION));
}
/**
* 1.如果不允许调用线程打开到指定主机和端口号的套接字连接,则抛出SecurityException。
* A port number of <code>-1</code> indicates that the calling
* method is attempting to determine the IP address of the specified
* host name.
* 2.-1的端口号表示调用方法正在尝试确定指定主机名的 IP 地址。
* 3.如果端口不等于 -1,则此方法使用SocketPermission(host+":"+port,"connect")权限调用checkPermission。
* 如果端口等于 -1,则它使用SocketPermission(host,"resolve")权限调用 checkPermission。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkConnect
*/
public void checkConnect(String host, int port) {
if (host == null) {
throw new NullPointerException("host can't be null");
}
if (!host.startsWith("[") && host.indexOf(':') != -1) {
host = "[" + host + "]";
}
if (port == -1) {
checkPermission(new SocketPermission(host,
SecurityConstants.SOCKET_RESOLVE_ACTION));
} else {
checkPermission(new SocketPermission(host+":"+port,
SecurityConstants.SOCKET_CONNECT_ACTION));
}
}
/**
* 1.如果不允许指定的安全上下文打开到指定主机和端口号的套接字连接,则抛出SecurityException。
* 2.-1的端口号表示调用方法正在尝试确定指定主机名的 IP 地址
* 3.如果context不是AccessControlContext的实例,则抛出SecurityException
* 4.否则,检查端口号。如果它不等于 -1,则context的checkPermission方法
* 将使用SocketPermission(host+":"+port,"connect")<code> 调用允许
* 5.如果端口等于 -1,则使用 <code>SocketPermission(host,"resolve")权限调用context的 checkPermission方法
* 6.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用 super.checkConnect
*/
public void checkConnect(String host, int port, Object context) {
if (host == null) {
throw new NullPointerException("host can't be null");
}
if (!host.startsWith("[") && host.indexOf(':') != -1) {
host = "[" + host + "]";
}
if (port == -1)
checkPermission(new SocketPermission(host,
SecurityConstants.SOCKET_RESOLVE_ACTION),
context);
else
checkPermission(new SocketPermission(host+":"+port,
SecurityConstants.SOCKET_CONNECT_ACTION),
context);
}
/**
* 1.如果不允许调用线程等待指定本地端口号上的连接请求,则抛出SecurityException。
* 2.此方法使用SocketPermission("localhost:"+port,"listen")调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkListen。
*/
public void checkListen(int port) {
checkPermission(new SocketPermission("localhost:"+port,
SecurityConstants.SOCKET_LISTEN_ACTION));
}
/**
* 1.如果不允许调用线程接受来自指定主机和端口号的套接字连接,则抛出SecurityException。
* 2.该方法由ServerSocket类的accept方法为当前安全管理器调用
* 3.此方法使用SocketPermission(host+":"+port,"accept")权限调用checkPermission
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkAccept。
*/
public void checkAccept(String host, int port) {
if (host == null) {
throw new NullPointerException("host can't be null");
}
if (!host.startsWith("[") && host.indexOf(':') != -1) {
host = "[" + host + "]";
}
checkPermission(new SocketPermission(host+":"+port,
SecurityConstants.SOCKET_ACCEPT_ACTION));
}
/**
* 1.如果不允许调用线程使用 (join/leave/send/receive) IP 多播,则抛出SecurityException
* 2.此方法使用 java.net.SocketPermission(maddr.getHostAddress(), "accept,connect")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkMulticast
*/
public void checkMulticast(InetAddress maddr) {
String host = maddr.getHostAddress();
if (!host.startsWith("[") && host.indexOf(':') != -1) {
host = "[" + host + "]";
}
checkPermission(new SocketPermission(host,
SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
}
/**
* 1.如果不允许调用线程使用 (join/leave/send/receive) IP 多播,则抛出SecurityException
* 2.此方法使用java.net.SocketPermission(maddr.getHostAddress(), "accept,connect")权限调用checkPermission
*3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkMulticast
*/
@Deprecated
public void checkMulticast(InetAddress maddr, byte ttl) {
String host = maddr.getHostAddress();
if (!host.startsWith("[") && host.indexOf(':') != -1) {
host = "[" + host + "]";
}
checkPermission(new SocketPermission(host,
SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
}
/**
* 1.如果不允许调用线程访问或修改系统属性,则抛出SecurityException
* 2.此方法由System类的getProperties和setProperties方法使用
* 3.此方法使用PropertyPermission("", "read,write")权限调用checkPermission。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkPropertiesAccess
*/
public void checkPropertiesAccess() {
checkPermission(new PropertyPermission("*",
SecurityConstants.PROPERTY_RW_ACTION));
}
/**
* 1.如果不允许调用线程使用指定的key名称访问系统属性,则抛出SecurityException
* 2.此方法由System类的getProperty方法使用
* 3.此方法使用PropertyPermission(key, "read")权限调用checkPermission。
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkPropertyAccess。
*/
public void checkPropertyAccess(String key) {
checkPermission(new PropertyPermission(key,
SecurityConstants.PROPERTY_READ_ACTION));
}
/**
* 1.如果调用线程不受信任以显示由window参数指示的顶级窗口,则返回false。
* 在这种情况下,调用者仍然可以决定显示该窗口,但该窗口应包含某种视觉警告。
* 如果该方法返回true,则可以在没有任何特殊限制的情况下显示该窗口
* 2.有关受信任和不受信任的窗口的更多信息,请参阅 class Window
* 2.此方法使用AWTPermission("showWindowWithoutWarningBanner")权限调用<checkPermission,
* 如果没有抛出SecurityException,则返回true,否则返回false。对于不包含java.awt包的 Java SE 子集配置文件,
* 会调用 checkPermission来检查权限 java.security.AllPermission。
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常返回false和super.checkTopLevelWindow的值时
* 调用 super.checkTopLevelWindow应该返回。
*/
@Deprecated
public boolean checkTopLevelWindow(Object window) {
if (window == null) {
throw new NullPointerException("window can't be null");
}
Permission perm = SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION;
if (perm == null) {
perm = SecurityConstants.ALL_PERMISSION;
}
try {
checkPermission(perm);
return true;
} catch (SecurityException se) {
// just return false
}
return false;
}
/**
* 1.如果不允许调用线程发起打印作业请求,则抛出SecurityException。
* 2.此方法使用RuntimePermission("queuePrintJob")权限调用checkPermission
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkPrintJobAccess。
*/
public void checkPrintJobAccess() {
checkPermission(new RuntimePermission("queuePrintJob"));
}
/**
* 1.如果不允许调用线程访问系统剪贴板,则抛出SecurityException
* 2.此方法使用AWTPermission("accessClipboard")权限调用 checkPermission。
* 3.对于不包含java.awt包的 Java SE 子集配置文件,会调用checkPermission来检查权限java.security.AllPermission
* 4.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkSystemClipboardAccess
*/
@Deprecated
public void checkSystemClipboardAccess() {
Permission perm = SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION;
if (perm == null) {
perm = SecurityConstants.ALL_PERMISSION;
}
checkPermission(perm);
}
/**
* 1.如果不允许调用线程访问 AWT 事件队列,则抛出SecurityException。
* 2.此方法使用 AWTPermission("accessEventQueue")权限调用checkPermission。对于不包含 java.awt包的 Java SE 子集配置文件,
* 会调用checkPermission来检查权限 java.security.AllPermission。
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用 super.checkAwtEventQueueAccess。
*/
@Deprecated
public void checkAwtEventQueueAccess() {
Permission perm = SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION;
if (perm == null) {
perm = SecurityConstants.ALL_PERMISSION;
}
checkPermission(perm);
}
/**
* 1.如果不允许调用线程访问参数指定的包,则抛出SecurityException
* 2.此方法由类加载器的loadClass方法使用。
* 2.此方法首先通过从对java.security.Security.getProperty("package.access")的调用中
* 获取以逗号分隔的列表来获取受限包列表,并检查pkg以或等于任何受限制的包开头。
* 如果是,则使用 RuntimePermission("accessClassInPackage."+pkg)权限调用checkPermission。
* 3.如果此方法被覆盖,则 super.checkPackageAccess应作为被覆盖方法的第一行调用
*/
public void checkPackageAccess(String pkg) {
if (pkg == null) {
throw new NullPointerException("package name can't be null");
}
String[] pkgs;
synchronized (packageAccessLock) {
/*
* Do we need to update our property array?
*/
if (!packageAccessValid) {
String tmpPropertyStr =
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return java.security.Security.getProperty(
"package.access");
}
}
);
packageAccess = getPackages(tmpPropertyStr);
packageAccessValid = true;
}
// Using a snapshot of packageAccess -- don't care if static field
// changes afterwards; array contents won't change.
pkgs = packageAccess;
}
/*
* Traverse the list of packages, check for any matches.
*/
for (int i = 0; i < pkgs.length; i++) {
if (pkg.startsWith(pkgs[i]) || pkgs[i].equals(pkg + ".")) {
checkPermission(
new RuntimePermission("accessClassInPackage."+pkg));
break; // No need to continue; only need to check this once
}
}
}
/**
* 1.如果不允许调用线程在参数指定的包中定义类,则抛出SecurityException。
* 2.某些类加载器的 loadClass方法使用此方法。
* 3.此方法首先通过从对java.security.Security.getProperty("package.definition")的调用中获取以逗号分隔的列表
* 来获取受限包列表,并检查pkg以或等于任何受限制的包开头。
* 如果是,则使用RuntimePermission("defineClassInPackage."+pkg)权限调用checkPermission。
* 4.如果此方法被覆盖,则 super.checkPackageDefinition应作为被覆盖方法的第一行调用。
*/
public void checkPackageDefinition(String pkg) {
if (pkg == null) {
throw new NullPointerException("package name can't be null");
}
String[] pkgs;
synchronized (packageDefinitionLock) {
/*
* Do we need to update our property array?
*/
if (!packageDefinitionValid) {
String tmpPropertyStr =
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return java.security.Security.getProperty(
"package.definition");
}
}
);
packageDefinition = getPackages(tmpPropertyStr);
packageDefinitionValid = true;
}
// Using a snapshot of packageDefinition -- don't care if static
// field changes afterwards; array contents won't change.
pkgs = packageDefinition;
}
/*
* Traverse the list of packages, check for any matches.
* //遍历包列表,检查是否有匹配项。
*/
for (int i = 0; i < pkgs.length; i++) {
if (pkg.startsWith(pkgs[i]) || pkgs[i].equals(pkg + ".")) {
checkPermission(
new RuntimePermission("defineClassInPackage."+pkg));
break; // No need to continue; only need to check this once
}
}
}
/**
* 1.如果不允许调用线程设置ServerSocket或Socket使用的套接字工厂,或 URL 使用的流处理程序工厂,
* 则抛出SecurityException。
* 2.此方法使用 RuntimePermission("setFactory")权限调用checkPermission。
* 3.如果您覆盖此方法,那么您应该在覆盖的方法通常会抛出异常时调用super.checkSetFactory。
*/
public void checkSetFactory() {
checkPermission(new RuntimePermission("setFactory"));
}
/**
* 1.如果不允许调用线程访问成员,则抛出SecurityException。
* 2.默认策略是允许访问 PUBLIC 成员,以及访问与调用者具有相同类加载器的类。
* 在所有其他情况下,此方法使用 RuntimePermission("accessDeclaredMembers")权限调用checkPermission。
*3.如果此方法被覆盖,则无法调用super.checkMemberAccess,因为checkMemberAccess的默认实现依赖于被检查的代码在堆栈深度为 4。
*/
@Deprecated
@CallerSensitive
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == null) {
throw new NullPointerException("class can't be null");
}
if (which != Member.PUBLIC) {
Class<?> stack[] = getClassContext();
/*
*堆栈深度 4 应该是 java.lang.Class 中调用 checkMember 访问的方法之一的调用者。
* 堆栈应如下所示:
* someCaller [3]
* java.lang.Class.someReflectionAPI [2]
* java.lang.Class.checkMemberAccess [1]
* SecurityManager.checkMemberAccess [0]
*/
if ((stack.length<4) ||
(stack[3].getClassLoader() != clazz.getClassLoader())) {
checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
}
}
/**
* 1.确定是授予还是拒绝具有指定权限目标名称的权限
* 2.如果请求的权限被允许,这个方法会安静地返回。如果被拒绝,则会引发 SecurityException。
* 3.此方法为给定的权限目标名称创建一个SecurityPermission对象,并用它调用checkPermission。
* 4.有关可能的权限目标名称的列表,请参阅java.security.SecurityPermission的文档。
* 5.如果您覆盖此方法,那么您应该在覆盖的方法通常会引发异常时调用super.checkSecurityAccess。
*/
public void checkSecurityAccess(String target) {
checkPermission(new SecurityPermission(target));
}
getThreadGroup
/**
* 返回线程组,将在调用时创建的任何新线程实例化到该线程组中。
* 默认情况下,它返回当前线程的线程组。这应该由特定的安全管理器覆盖以返回适当的线程组。
*/
public ThreadGroup getThreadGroup() {
return Thread.currentThread().getThreadGroup();
}
六.总结
SecurityManager类,正常的程序员应该都不会跟他打交道了...