【问题标题】:Deploy a Java Applet with Security Permission in HTML在 HTML 中部署具有安全权限的 Java 小程序
【发布时间】:2011-08-08 01:10:09
【问题描述】:

我很难让它发挥作用。

小程序嵌入在我的web page 中,它正在尝试连接到 Java Servlet here

在某些计算机上连接正常,在其他计算机上出现无法连接错误,我认为这是由 java 安全权限引起的。

自定义1:拒绝访问(java.net.SocketPermission 184.91.186.5:8080 connect,resolve)

java.security.AccessControlException: access denied (java.net.SocketPermission 184.91.186.5:8080 connect,resolve)
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkConnect(Unknown Source)
    at sun.plugin2.applet.Applet2SecurityManager.checkConnect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at sun.net.NetworkClient.doConnect(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.<init>(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
    at Calendar_Algorithm$Con.send_courses_to_server(Calendar_Algorithm.java:789)
    at Calendar_Algorithm$Con.run(Calendar_Algorithm.java:773)
    at Calendar_Algorithm.send_courses_to_server(Calendar_Algorithm.java:761)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
    at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source)
    at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source)
    at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source)
    at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source)
    at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source)
    at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source)
    at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

我已经签署了 jar 文件,但仍然无法解决问题。 这是我生成密钥文件并签署 jar 的方式。

keytool -genkey -alias cal -keystore keys  -keypass #### -dname "cn=feldman" -storepass ####

jarsigner -keystore keys -storepass #### -keypass #### -signedjar CalSigned.jar Cal.jar cal

这是我将它嵌入到 html 页面的方式:

<script src="http://java.com/js/deployJava.js"></script>

    <script>
        var attributes = {code:'Calendar_Algorithm.class',
                      archive:'Cal39.jar',
                      width:150, height:50,
                      id:"ClientApp",
                      name:"ClientApp"
                      } ;
        var parameters = {fontSize:16} ;
        var version = '1.6' ;
        deployJava.runApplet(attributes, parameters, version);
    </script>

我也试过做一个 jnlp 文件,但我什至无法启动 jar,这是我的 jnlp 文件内容:

  <?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="" href="">
    <security>
        <all-permissions/>
    </security>
    <information>
        <title>Easy Course Selector</title> 
        <vendor>Group Boba</vendor>
        <homepage href="index.html"/>
        <description>Easy Course Selector</description>
        <description kind="short">Easy Course Selector</description>
        <icon href="mouseguard-small-jpg3.jpg"/>

    </information>

    <resources>
        <j2se version="1.5+" href="http://java.sun.com/products/autodl/j2se" />
        <jar href="Cal.jar" main="true" download="eager" />
    </resources>
    <applet-desc name="EasyCourse Applet" main-class="Calendar_Algorithm.class" width="200" height="50">
    </applet-desc>
    <update check="background"/>
</jnlp> 

以及嵌入代码

<script> 
    var attributes = {id:"ClientApp", name:"ClientApp", code:'Calendar_Algorithm',   width:150, height:50} ; 
    var parameters = {jnlp_href: 'Cal_Info.jnlp'} ; 
    deployJava.runApplet(attributes, parameters, '1.6'); 
</script>

这是我使用它连接外部服务器时的错误日志:

java.security.AccessControlException: access denied (java.net.SocketPermission 184.91.186.5:8080 connect,resolve)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkConnect(Unknown Source)
at sun.plugin2.applet.Applet2SecurityManager.checkConnect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at Calendar_Algorithm$Con.send_courses_to_server(Calendar_Algorithm.java:789)
at Calendar_Algorithm$Con.run(Calendar_Algorithm.java:773)
at Calendar_Algorithm.send_courses_to_server(Calendar_Algorithm.java:761)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

任何帮助都会很棒。

这里也是导致错误的代码:

class Con implements PrivilegedExceptionAction<Boolean> {
    private final String text;
    boolean res;
    public Con(String t) {
      text=t;
    }

    public Boolean run() { 
      res=send_courses_to_server();
      return res;
    } 
    public boolean send_courses_to_server(){

        try {
            URL url = new URL(server);

            HttpURLConnection con;
            con=(HttpURLConnection) url.openConnection();
            con.setRequestProperty("Content-type", "text/xml; charset=UTF-8");
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);


            OutputStream out = con.getOutputStream();
            Writer writer = new OutputStreamWriter(out, "UTF-8");
            String xml="";
            writer.write("<Request>\n" +"<Request_Type>Validation_2</Request_Type>\n");
            xml="<Request>\n" +"<Request_Type>Validation_2</Request_Type>\n";



            Scanner in=new Scanner(text);
            while(in.hasNext()){
                String temp=in.nextLine().trim();
                writer.write("<Course>"+temp+"</Course>\n");
                xml=xml+"<Course>"+temp+"</Course>\n";
            }
            writer.write("</Request>\n");
            xml=xml+"</Request>\n";

            writer.flush();
            writer.close();

            InputStream is= con.getInputStream();

            if(con.getContentType().equals("text/xml")){
                status_message= new Scanner(is).nextLine();
                return false;
            }
            else{
                return set_courses(is);
            }

        } catch (Exception e){
            e.printStackTrace();
            status_message= "Custom 1: "+e.getMessage();
            return false;
        }

    }

    private boolean set_courses(InputStream is){
        courses=new Vector<Course>();

        try {
            ObjectInputStream ois=new ObjectInputStream(is);

            Course c;
            while(true){
                try{
                    c=(Course)ois.readObject();
                    courses.add(c);
                }catch(EOFException e){
                    break;
                }
            }
            ois.close();
        } catch (Exception e){
            status_message= "Custom 3 "+e.getMessage();
            return false;
        }
        status_message="Good";
        return true;
    }

}

【问题讨论】:

  • 你能显示你得到的异常吗?此外,您的 JNLP 文件似乎有点小。
  • 访问被拒绝 (java.net.SocketPermission 184.91.186.5:8080 connect,resolve) 我必须切换操作系统才能得到错误,IP 是 servlet 的 IP
  • @Paulo Ebermann,我很难为 jnlp 文件找到一个好的指南,你能给我一些改进我的建议吗?
  • 有趣的部分是堆栈跟踪,即异常发生的地方。代替e.getMessage() 执行e.printStackTrace() 并查看Java 控制台。 (并将其添加到问题中,而不是作为评论。)
  • 好的,现在您的 jnlp 文件可见(提示:添加 4 个空格以缩进代码,然后引擎不会尝试将标签解释为 HTML)。 applet-desc 元素应该命名您将在“通常”情况下使用的相同的小程序类。有关详细信息,请查看 Java 教程的 Applet Deployment 部分。

标签: java html security applet embed


【解决方案1】:

现在,通过堆栈跟踪,我们可以更好地了解原因。

...
at Calendar_Algorithm$Con.send_courses_to_server(Calendar_Algorithm.java:789)
at Calendar_Algorithm$Con.run(Calendar_Algorithm.java:773)
at Calendar_Algorithm.send_courses_to_server(Calendar_Algorithm.java:761)
...
at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
...

您似乎正在使用 JavaScript 来调用您的小程序的方法。您的CalendarAlgorithm 类的send_courses_to_server 方法是从JavaScript 调用的,并直接调用您的Con 内部类的run 方法。这意味着您的代码(仅)使用外部 JavaScript 的权限运行,而不是您的小程序的权限。

Con 类扩展了PrivilegedExceptionAction,但仅此还不足以提供特权执行。您还必须将其包装在对 AccessController.doPrivileged(...) 的调用中(这里给出您的 Con 对象)。

然后将使用通过签名授予您的小程序的权限调用该方法。 (当然,您应该在此之前检查此调用是否合法且没有任何恶意。)

我想你的签名工作,我没有检查这个,因为我通常使用未签名的小程序。顺便说一句,如果您的小程序与 servlet 来自同一台服务器,则此连接不需要任何签名。

【讨论】:

  • 所以如果我这样做: public boolean send_courses_to_server(String t){ con.set_text(t); AccessController.doPrivileged(con.run());返回 con.res; },它应该工作吗?还是你的意思是当我从 JavaScript 拨打电话时?
  • 不,做return AccessController.doPrivileged(con);。您不必自己调用run 方法,AccessController 会这样做。
  • 假设通过该更改我不需要 jnlp 文件是否正确?如果他们对彼此有利?
  • JNLP 文件只是执行此操作的另一种(较新)方法。有些属性只能用 JNLP 文件设置,未签名的 JNLP 小程序可以访问 JNLP API(在用户批准的情况下进行本地访问),而标准小程序不能(在 Sun VM 上)。 IcedTea 和当前的 Mac OS 虚拟机似乎不支持 jnlp 文件(但在 IcedTea 中,您仍然可以访问 JNLP API,也可以使用普通的小程序)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-07
  • 2014-03-22
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多