zoukankan      html  css  js  c++  java
  • Java安全管理器(Security Manager)

    本文转载自:http://blog.sina.com.cn/s/blog_4b00fd1b0100c9ef.html

    看源码的时候发现很多地方都有SecurityManager的身影。。感谢分享。。

    每个Java应用都可以有自己的安全管理器,它是防范恶意攻击的主要安全卫士。安全管理器通过执行运行阶段检查和访问授权,以实施应用所需的安全策略,从而保护资源免受恶意操作的攻击。实际上,安全管理器根据Java安全策略文件决定将哪组权限授予类。然而,当不可信的类和第三方应用使用JVM时,Java安全管理器将使用与JVM相关的安全策略来识别恶意操作。在很多情况下,威胁模型不包含运行于JVM中的恶意代码,此时Java安全管理器便不是必需的。当安全管理器检测到违反安全策略的操作时,JVM将引发AccessControlException或SecurityException。

        在Java应用中,安全管理器是由System类中的方法setSecurityManager设置的。要获得当前的安全管理器,可以使用方法getSecurityManager。

       java.lang.SecurityManager类包含了很多checkXXXX方法,如用于判断对文件访问权限的checkRead(String file)方法。这些检查方法调用SecurityManager.checkPermission方法,后者根据安全策略文件判断调用应用是否有执行所请求的操作权限。如果没有,将引发SecurityException。

        如果想让应用使用安全管理器和安全策略,可在启动JVM时设定-Djava.security.manager选项,还可以同时指定安全策略文件。如果在 应用中启用了Java安全管理器,却没有指定安全策略文件,那么Java安全管理器将使用默认的安全策略,它们是由位于目录$JAVA_HOME/jre /lib/security中的java.policy定义的。

    概念
    策略(Policy)
        类装载器用Policy对象帮助它们决定,把一段代码导入虚拟机时应该给它们什么样的权限. 任何时候,每一个应用程序都只有一个Policy对象.
    策略文件
        Sun的java1.2平台具体的Policy子类采用在一ASCII策略文件中用上下文无关文法描述安全策略.
        一个策略文件包括了一系列grant子句,每一个grant子句将一些权限授给一个代码来源。
    保护域(ProtectionDomain)
        当类装载器将类型装入java虚拟机时,它们将为每一个类型指派一个保护域,保护域定义了授予
       一段特定的代码的所有权限.装载入java虚拟机的每一个类型都属于一个且仅属于一个保护域.
    访问控制器(AccessController)
         implies()
              判断一个Permissioin对象的权限,是否隐含(imply)在另一个Permissioin对象的权限中。
        checkPermission()
             AccessController的核心方法,这个方法决定一个特定的操作能否被允许.
             它自顶向下检查栈,只要它遇到一个没有权限桢,它将抛出一个AccessControlException导常。
        doPrivileged()
             有的时候,调用栈较上层(更靠近栈顶)的代码可能希望执行一段代码,而这段代码在调用栈的较
             下层是不允许执行的。
              为了使可信的代码执行较不可靠的代码操作(这段不可靠的代码位于调用栈的较下层且没有执行
              这个操作的权限),AccessController类重载了四个名为doPrivileged()的静态方法.
              AccessController会忽略调用doPrivileged()方法的调用者的调用者的权限.
        Permission:
              权限是用抽象类java.security.Permission的一个子类的实例表示的.
        CodeSource:
             代码来源,包含代码库URL和签名者.
        Permissions:
            PermissionCollection(权限集合)的子类
            
    装载时生成保护域的步骤:
    1           根据指定的Policy文件生成一个Policy对象
    2           生成CodeSource
    3           用CodeSource在Policy中找到CodeSource对应的Permissions
    4           用CodeSource和Permissons构造一个ProtectionDomain
    5           把ProtectionDomain同这个类在方法区中的类数据联系起来(ClassLoader.defineClass()).
     
     
     运行权限检查:
    如当前应用程序执行new FileInputStream(“a.txt”),java会检查当前代码有没有读”a.txt”的权限.
    步骤:
    1           调用SecurityManager.checkRead()方法
    2           调用AccessControl.checkPermission()方法,执行栈检查

    实现安全管理器步骤:

    (1) 创建一个SecurityManager的子类;
    (2) 覆盖一些方法。
    import java.io.*;

    public class TestSecurity
    {
       public static void main(String args[])
       {
            try {
                   System.setSecurityManager(new PasswordSecurityManager("123456"));
                } catch (SecurityException se) {
                    System.out.println("SecurityManager already set!");
                }
            try {
                //DataInputStream fis = new DataInputStream(new FileInputStream("input.txt"));
                BufferedReader fis = new BufferedReader(new FileReader("input.txt"));
                //DataOutputStream fos = new DataOutputStream( new FileOutputStream("output.txt"));
                BufferedWriter fos = new BufferedWriter(new FileWriter("output.txt"));
                String inputString;
                while ((inputString = fis.readLine()) != null) {
            //fos.writeBytes(inputString);
            //fos.writeByte('\n');
            fos.write(inputString);
            fos.write('\n');
                }
                fis.close();
                fos.close();
            } catch (IOException ioe) {
                System.out.println("I/O failed for SecurityManagerTest.");
            }catch(Exception e)
            {
               System.out.println(e.toString());
            }
          
       }
    }
     
     
    import java.io.*;
    class PasswordSecurityManager extends SecurityManager {
    private String password;
    PasswordSecurityManager(String password) {
        super();
        this.password = password;
    }
    private boolean accessOK() {
        int c;
        //DataInputStream dis = new DataInputStream(System.in);
        BufferedReader dis = new BufferedReader(new InputStreamReader(System.in));
        String response;
        System.out.println("What's the secret password?");
        try {
            response = dis.readLine();
            if (response.equals(password))
                return true;
            else
                return false;
        } catch (IOException e) {
            return false;
        }
    }
    public void checkRead(FileDescriptor filedescriptor) {
        if (!accessOK())
            throw new SecurityException("Not a Chance!");
    }
    public void checkRead(String filename) {
        if (!accessOK())
            throw new SecurityException("No Way!");
    }
    public void checkRead(String filename, Object executionContext) {
        if (!accessOK())
            throw new SecurityException("Forget It!");
    }
    public void checkWrite(FileDescriptor filedescriptor) {
        if (!accessOK())
            throw new SecurityException("Not!");
    }
    public void checkWrite(String filename) {
        if (!accessOK())
            throw new SecurityException("Not Even!");
    }
    }

  • 相关阅读:
    第三天 moyax
    mkfs.ext3 option
    write file to stroage trigger kernel warning
    download fomat install rootfs script
    custom usb-seriel udev relus for compatible usb-seriel devices using kermit
    Wifi Troughput Test using iperf
    learning uboot switch to standby system using button
    learning uboot support web http function in qca4531 cpu
    learngin uboot design parameter recovery mechanism
    learning uboot auto switch to stanbdy system in qca4531 cpu
  • 原文地址:https://www.cnblogs.com/charlexu/p/3029201.html
Copyright © 2011-2022 走看看