• Tomcat你很少使用的安全管理SecurityManager


    试想一下,如果你的JSP页面中包含一句代码“System.exit(1);”,你的web应用访问到该JSP时,会发生什么?
    
    一般使用tomcat可能都没有注意到这个问题,本篇主要讲述tomcat 6中SecurityManager的管理机制,尽量使用简单明了的图片表示其中关系。
    
    其他知识参考tomcat文档翻译。如有错误,请予指正。
    
    理解java.policy
    
      Java是一门安全性很高的语言,因此也会考虑到用户代码对整个系统的侵入性。试想一下,如果你引用了一个jar包,里面包含了依据system.exit(),每次执行到这里都直接退出,会不会很蛋疼!
    
      Java开发者肯定想过如此的问题,所以引入了java安全策略机制,利用一个配置文件来管理所有的代码权限。
    
      JDK中就有这样的文件,就是  jre/lib/security/java.policy  ,参考下该文件,就能理解其中的关系:
    
     
    
    复制代码
    // default permissions granted to all domains
    grant {
            // Allows any thread to stop itself using the java.lang.Thread.stop()
            // method that takes no argument.
            // Note that this permission is granted by default only to remain
            // backwards compatible.
            // It is strongly recommended that you either remove this permission
            // from this policy file or further restrict it to code sources
            // that you specify, because Thread.stop() is potentially unsafe.
            // See the API specification of java.lang.Thread.stop() for more
            // information.
            permission java.lang.RuntimePermission "stopThread";
    
            // allows anyone to listen on dynamic ports
            permission java.net.SocketPermission "localhost:0", "listen";
    
            // "standard" properies that can be read by anyone
    
            permission java.util.PropertyPermission "java.version", "read";
            permission java.util.PropertyPermission "java.vendor", "read";
            permission java.util.PropertyPermission "java.vendor.url", "read";
            permission java.util.PropertyPermission "java.class.version", "read";
            permission java.util.PropertyPermission "os.name", "read";
            permission java.util.PropertyPermission "os.version", "read";
            permission java.util.PropertyPermission "os.arch", "read";
            permission java.util.PropertyPermission "file.separator", "read";
            permission java.util.PropertyPermission "path.separator", "read";
            permission java.util.PropertyPermission "line.separator", "read";
    
            permission java.util.PropertyPermission "java.specification.version", "read";
            permission java.util.PropertyPermission "java.specification.vendor", "read";
            permission java.util.PropertyPermission "java.specification.name", "read";
    
            permission java.util.PropertyPermission "java.vm.specification.version", "read";
            permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
            permission java.util.PropertyPermission "java.vm.specification.name", "read";
            permission java.util.PropertyPermission "java.vm.version", "read";
            permission java.util.PropertyPermission "java.vm.vendor", "read";
            permission java.util.PropertyPermission "java.vm.name", "read";
    };
    
    复制代码
    
      上面给出了基本的权限,例如任何人都可以监听动态端口,以及一些读操作。
    
      基本过程如下面的图所示:
    
    
    
     
    
      用户如果启用了安全管理,即在执行时添加了-Djava.security.manager, 就会在执行某些操作前 先读取 权限文件java.policy,检查是否具体相应权限。
    
      当然也可以自己定义安全文件,一般有两种方式:
    
      一种是自己创建SecuirtyManager类,创建一些checkXXX的方法,进行验证;
    
      另一种就是创建my.policy文件(名字随意),按照规定的语法配置权限,然后启动时添加-Djava.security.manager-Djava.security.policy=xxxx/my.policy参数。
    
      关于java本身的安全管理不是本篇的重点,下面介绍下tomcat中的安全策略。
    
    理解tomcat中的Security
    
      Tomcat中的安全管理原理基本与前面JDK中的security类似,只是启动时需要在start后面添加-security参数,tomcat会自动读取 conf/catalina.policy 文件中的权限配置。启动命令如下:
    
    F:apache-tomcat-xxx/bin/startup.bat -security
    
      catalina.policy中默认已经配置了很多的安全策略,这里就不多说明了,下个部分会针对某一特定文件进行说明:
    
     
    
    复制代码
    // Licensed to the Apache Software Foundation (ASF) under one or more
    // contributor license agreements.  See the NOTICE file distributed with
    // this work for additional information regarding copyright ownership.
    // The ASF licenses this file to You under the Apache License, Version 2.0
    // (the "License"); you may not use this file except in compliance with
    // the License.  You may obtain a copy of the License at
    //
    //     http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    // ============================================================================
    // catalina.policy - Security Policy Permissions for Tomcat 6
    //
    // This file contains a default set of security policies to be enforced (by the
    // JVM) when Catalina is executed with the "-security" option.  In addition
    // to the permissions granted here, the following additional permissions are
    // granted to the codebase specific to each web application:
    //
    // * Read access to its document root directory
    // * Read, write and delete access to its working directory
    // ============================================================================
    
    
    // ========== SYSTEM CODE PERMISSIONS =========================================
    
    
    // These permissions apply to javac
    grant codeBase "file:${java.home}/lib/-" {
            permission java.security.AllPermission;
    };
    
    // These permissions apply to all shared system extensions
    grant codeBase "file:${java.home}/jre/lib/ext/-" {
            permission java.security.AllPermission;
    };
    
    // These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre
    grant codeBase "file:${java.home}/../lib/-" {
            permission java.security.AllPermission;
    };
    
    // These permissions apply to all shared system extensions when
    // ${java.home} points at $JAVA_HOME/jre
    grant codeBase "file:${java.home}/lib/ext/-" {
            permission java.security.AllPermission;
    };
    
    
    // ========== CATALINA CODE PERMISSIONS =======================================
    
    
    // These permissions apply to the daemon code
    grant codeBase "file:${catalina.home}/bin/commons-daemon.jar" {
            permission java.security.AllPermission;
    };
    
    // These permissions apply to the logging API
    // Note: If tomcat-juli.jar is in ${catalina.base} and not in ${catalina.home},
    // update this section accordingly.
    //  grant codeBase "file:${catalina.base}/bin/tomcat-juli.jar" {..}
    grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
            permission java.io.FilePermission
             "${java.home}${file.separator}lib${file.separator}logging.properties", "read"; 
    
            permission java.io.FilePermission
             "${catalina.base}${file.separator}conf${file.separator}logging.properties", "read";
            permission java.io.FilePermission
             "${catalina.base}${file.separator}logs", "read, write";
            permission java.io.FilePermission
             "${catalina.base}${file.separator}logs${file.separator}*", "read, write";
    
            permission java.lang.RuntimePermission "shutdownHooks";
            permission java.lang.RuntimePermission "getClassLoader";
            permission java.lang.RuntimePermission "setContextClassLoader";
    
            permission java.util.logging.LoggingPermission "control";
    
            permission java.util.PropertyPermission "java.util.logging.config.class", "read";
            permission java.util.PropertyPermission "java.util.logging.config.file", "read";
            permission java.util.PropertyPermission "catalina.base", "read";
    
            // Note: To enable per context logging configuration, permit read access to
            // the appropriate file. Be sure that the logging configuration is
            // secure before enabling such access.
            // E.g. for the examples web application (uncomment and unwrap
            // the following to be on a single line):
            // permission java.io.FilePermission "${catalina.base}${file.separator}
            //  webapps${file.separator}examples${file.separator}WEB-INF
            //  ${file.separator}classes${file.separator}logging.properties", "read";
    };
    
    // These permissions apply to the server startup code
    grant codeBase "file:${catalina.home}/bin/bootstrap.jar" {
            permission java.security.AllPermission;
    };
    
    // These permissions apply to the servlet API classes
    // and those that are shared across all class loaders
    // located in the "lib" directory
    grant codeBase "file:${catalina.home}/lib/-" {
            permission java.security.AllPermission;
    };
    
    
    // If using a per instance lib directory, i.e. ${catalina.base}/lib,
    // then the following permission will need to be uncommented
    // grant codeBase "file:${catalina.base}/lib/-" {
    //         permission java.security.AllPermission;
    // };
    
    
    // ========== WEB APPLICATION PERMISSIONS =====================================
    
    
    // These permissions are granted by default to all web applications
    // In addition, a web application will be given a read FilePermission
    // and JndiPermission for all files and directories in its document root.
    grant { 
        // Required for JNDI lookup of named JDBC DataSource's and
        // javamail named MimePart DataSource used to send mail
        permission java.util.PropertyPermission "java.home", "read";
        permission java.util.PropertyPermission "java.naming.*", "read";
        permission java.util.PropertyPermission "javax.sql.*", "read";
    
        // OS Specific properties to allow read access
        permission java.util.PropertyPermission "os.name", "read";
        permission java.util.PropertyPermission "os.version", "read";
        permission java.util.PropertyPermission "os.arch", "read";
        permission java.util.PropertyPermission "file.separator", "read";
        permission java.util.PropertyPermission "path.separator", "read";
        permission java.util.PropertyPermission "line.separator", "read";
    
        // JVM properties to allow read access
        permission java.util.PropertyPermission "java.version", "read";
        permission java.util.PropertyPermission "java.vendor", "read";
        permission java.util.PropertyPermission "java.vendor.url", "read";
        permission java.util.PropertyPermission "java.class.version", "read";
        permission java.util.PropertyPermission "java.specification.version", "read";
        permission java.util.PropertyPermission "java.specification.vendor", "read";
        permission java.util.PropertyPermission "java.specification.name", "read";
    
        permission java.util.PropertyPermission "java.vm.specification.version", "read";
        permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
        permission java.util.PropertyPermission "java.vm.specification.name", "read";
        permission java.util.PropertyPermission "java.vm.version", "read";
        permission java.util.PropertyPermission "java.vm.vendor", "read";
        permission java.util.PropertyPermission "java.vm.name", "read";
    
        // Required for OpenJMX
        permission java.lang.RuntimePermission "getAttribute";
    
        // Allow read of JAXP compliant XML parser debug
        permission java.util.PropertyPermission "jaxp.debug", "read";
    
        // Precompiled JSPs need access to these packages.
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.el";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime.*";
        
        // Precompiled JSPs need access to these system properties.
        permission java.util.PropertyPermission
         "org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "read";
        permission java.util.PropertyPermission "org.apache.el.parser.COERCE_TO_ZERO", "read";
    };
    
    
    // The Manager application needs access to the following packages to support the
    // session display functionality. These settings support the following
    // configurations:
    // - default CATALINA_HOME == CATALINA_BASE
    // - CATALINA_HOME != CATALINA_BASE, per instance Manager in CATALINA_BASE
    // - CATALINA_HOME != CATALINA_BASE, shared Manager in CATALINA_HOME
    grant codeBase "file:${catalina.base}/webapps/manager/-" {
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager.util";
    };
    grant codeBase "file:${catalina.home}/webapps/manager/-" {
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager";
        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager.util";
    };
    
    // You can assign additional permissions to particular web applications by
    // adding additional "grant" entries here, based on the code base for that
    // application, /WEB-INF/classes/, or /WEB-INF/lib/ jar files.
    //
    // Different permissions can be granted to JSP pages, classes loaded from
    // the /WEB-INF/classes/ directory, all jar files in the /WEB-INF/lib/
    // directory, or even to individual jar files in the /WEB-INF/lib/ directory.
    //
    // For instance, assume that the standard "examples" application
    // included a JDBC driver that needed to establish a network connection to the
    // corresponding database and used the scrape taglib to get the weather from
    // the NOAA web server.  You might create a "grant" entries like this:
    //
    // The permissions granted to the context root directory apply to JSP pages.
    // grant codeBase "file:${catalina.base}/webapps/examples/-" {
    //      permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
    //      permission java.net.SocketPermission "*.noaa.gov:80", "connect";
    // };
    //
    // The permissions granted to the context WEB-INF/classes directory
    // grant codeBase "file:${catalina.base}/webapps/examples/WEB-INF/classes/-" {
    // };
    //
    // The permission granted to your JDBC driver
    // grant codeBase "jar:file:${catalina.base}/webapps/examples/WEB-INF/lib/driver.jar!/-" {
    //      permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
    // };
    // The permission granted to the scrape taglib
    // grant codeBase "jar:file:${catalina.base}/webapps/examples/WEB-INF/lib/scrape.jar!/-" {
    //      permission java.net.SocketPermission "*.noaa.gov:80", "connect";
    // };
    
    复制代码
    
      这里需要注意的是其配置语法:
    
    grant [signedBy <signer>,] [codeBase <code source>] {
      permission  <class>  [<name> [, <action list>]];
    };
    
      都要按照上面的格式进行配置。其中:
    
      codeBase 是通过URL的方式指定文件,可以使用变量java.home或者 java.home或者{catalina.home}来表示JDK和tomcat的根目录。
    
      class 指定了相应的操作
    
      [name,[,action]] name指定具体的操作或者文件,action指定可选的动作(比如read write等等)。
    
      具体的配置样例,可以参考上面的默认文件。
    
      
    
      另外要说明的就是都可以配置哪些操作,也就是permission后面都可以跟哪些类,他们的作用都是什么?
    
    
    
      上面列表中,最常用的java.io.FilePermission用于文件的操作、java.lang.RuntimePermission(可以通过禁用该权限达到防止system.exit(1)的目的)等等。
    
    Security配置实战
    
      在tomcat中配置security,可以按照下面几个步骤:
    
      1 在样例代码中执行特殊权限操作:
    
     
    
    复制代码
    <%@ page language="java" contentType="text/html; charset=utf-8"
        import="java.net.*,java.io.*"
        pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>security Test</title>
    </head>
    <body>
        <h1>security Test</h1>
        <hr>
        <%!
        String txt2String(File file){
            String result = "";
            try{
                BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
                String s = null;
                while((s = br.readLine())!=null){//使用readLine方法,一次读一行
                    result = result + "
    " +s;
                }
                br.close();    
            }catch(Exception e){
                e.printStackTrace();
            }
            return result;
        }
        %>
        <%
        //是否启用了security,如果没有启用会输入null。
        System.out.println("SecurityManager: " + System.getSecurityManager());
        File file = new File("C:/Users/Administrator/Desktop/test.txt");
        //执行文件读操作,即java.io.FilePermission
        System.out.println(txt2String(file));
        //执行获取文件属性操作,即java.util.PropertyPermission
        System.out.println(System.getProperty("file.encoding"));
        %>
    </body>
    </html>
    
    复制代码
    
      当访问该页面时,会自动执行下面的代码,如果不具有相应的权限,会直接报错:
    
        //执行文件读操作,即java.io.FilePermission
        System.out.println(txt2String(file));
        //执行获取文件属性操作,即java.util.PropertyPermission
        System.out.println(System.getProperty("file.encoding"));
    
      2 配置安全策略文件catalina.policy:
    
      只需要在catalina.policy末尾添加如下的配置即可:
    
    grant { 
        permission java.io.FilePermission "C:/Users/Administrator/Desktop/test.txt", "read";
        permission java.util.PropertyPermission "file.encoding", "read";
    };
    
      3 在命令行中添加-security启动
    
    
    
      访问JSP执行代码,样例中访问 http://localhost:8080/JSPTest/securityTest.jsp
    
      可以看到控制台正常输出:
    
    
    
     
    
      对比下正常启动的输出,SecurityManager会输出null(此时,如果JSP中有system.exit(1);程序就会直接退出):
    
    
    
     
    
      如果没有配置读写文件的权限,会报错(注释掉安全配置的第一句):
    
    grant { 
        //permission java.io.FilePermission "C:/Users/Administrator/Desktop/test.txt", "read";
        permission java.util.PropertyPermission "file.encoding", "read";
    };
    
    
    
     
    
      如果没有配置获取文件属性权限,则会报错:
    
    grant { 
        permission java.io.FilePermission "C:/Users/Administrator/Desktop/test.txt", "read";
        //permission java.util.PropertyPermission "file.encoding", "read";
    };
    
    
    
     
    
      因此,如果在安全管理模式下,进行了越权的操作,就会报错有的甚至直接导致程序退出。
    
      通过报错信息,可以快速的知道缺乏什么权限,根绝该报错就可以方便的配置安全策略。
    
    参考
    
    【1】Java.security.policy文件:http://www.tmser.com/post-187.html
    2】Java安全管理器:http://bubuko.com/infodetail-306759.html
  • 相关阅读:
    uva514Rails(栈)
    hdu1160FatMouse's Speed
    如何截取整个屏幕
    equals 与==
    (转载)equals与==
    (转载)关于ArrayList的5道面试题
    java的一些程序
    (转载)OSI七层参考模型和TCP/IP四层参考模型
    (转载)算法面试题
    (转载)火车运煤
  • 原文地址:https://www.cnblogs.com/firstdream/p/8392900.html
Copyright © 2020-2023  润新知