为 HTML 中嵌入的 Applet 设置策略

发布于 2024-10-22 20:29:03 字数 1453 浏览 6 评论 0原文

我设计了一个小程序来使用 java.awt.Robot 类截取屏幕截图并将其保存在用户计算机上。我需要将此小程序嵌入到 html 页面中(使用对象标记),以便当用户单击网页上的按钮时截取屏幕截图。

小程序本身工作正常,我通过向其中添加临时 main 方法并将其作为常规 java 应用程序在我的本地计算机上运行来对其进行了测试。

我遇到困难的地方是设置权限以允许它从嵌入位置运行。显然,机器人类有些危险,因此需要建立 AWTPermission 并且需要对小程序本身进行签名。

我按照 http://download.oracle.com/javase 上的教程进行操作/tutorial/security/toolsign/index.html 并成功创建了一个签名的 .jar 文件,然后是一个允许该教程中的演示应用程序运行的策略文件。我现在遇到的问题是如何将我所学到的知识与小程序的使用情况相协调。

我的目标受众包括大约 100 台机器,我需要它能够在所有机器上执行。我已将 java .class 文件打包到 .jar 中,并使用 keytool 和 jarsigner 对其进行签名。然后,我将 .jar 和 .cer 文件上传到托管相关页面的服务器目录。

但是:当我使用策略工具在其中一台计算机上创建新的策略文件来测试设置时,我仍然无法从 HTML 执行小程序。我收到 Java.Security.AccessControlException Acess Denied java.awt.AWTPermission createRobot 错误。

我相当怀疑政策步骤出了问题,所以我将概述我所采取的步骤: 我将证书下载到本地计算机并从中生成密钥库,我通过命令行从此目录启动“policytool” 我在本地计算机上添加生成密钥库和我的证书所在的目录。 然后,我点击添加策略按钮并输入 SignedBy 别名 然后添加权限并选择 AWTPermission 目标名称我选择createRobot 我一直将功能字段留空,因为我无法想象这里适用什么 此窗口中的签名者也留空 然后,我点击“确定”和“完成”,并收到一条警告,提示我在第一步中输入的别名没有公钥。我执行“另存为”并将策略文件保存到放置证书和从其生成的密钥库的同一目录中。

然而,这不允许我从网页运行小程序,而且我对编程这方面的有限理解没有提供任何关于出了什么问题的线索。

想法、想法、观察?如果我没有明确提到某件事,那么我就没有这样做。我最大的怀疑是我收到的警告,但我似乎无法找到它出现的原因

编辑:忘记提及一个步骤。我手动将“policy.url.3=file:/C:/Testing/debugpolicy”行添加到我的 jre\lib\security\java.security 文件中,因为这是我在上述步骤中创建的路径和策略文件名。我现在还设法删除了之前提到的警告,我混淆了我的别名,并在创建策略文件期间为私有密钥库而不是公共密钥库提供了别名,但是我仍然遇到相同的问题

I have designed an Applet to take a screenshot and save it on the users computer using the java.awt.Robot class. I need to embedd this applet into an html page (using the object tag) so that when the user clicks a button on the webpage the screenshot is taken.

The applet itself works fine, i've tested it by adding a temporary main method to it and running it on my local machine as a regular java app.

Where I'm having difficulty is setting up permissions to allow it to run from its embedded location. Obviously the robot class is somewhat hazardous so an AWTPermission needs to be established and the applet itself needs to be signed.

I followed through the tutorial at http://download.oracle.com/javase/tutorial/security/toolsign/index.html and succeeded in creating a signed .jar file and then a policy file that allowed the demo application in that tutorial to run. Where I am now running into issues is how to reconcile what I've learned with the situation my applet will be used in.

My target audience comprises around 100 machines and I need it to be executable on all of them. I have packed my java .class file into a .jar and signed it using keytool and jarsigner. I then uploaded the .jar and .cer files to the server directory where the pages in question are hosted.

However: When I then used policytool to create a new policy file on one of the machines to test the setup I am still unable to execute the applet from the HTML. I get Java.Security.AccessControlException Acess Denied java.awt.AWTPermission createRobot errors.

I rather suspect its the policy step that is going awry, so I'll outline the steps I took:
I download the certificate to the local machine and generate a keystore from it, I launch 'policytool' from this directory through the commandline
I add the directory on the local machine where the keystore generated from and my certificate is located.
I then hit the add policy button and enter the SignedBy alias
Then Add Permissions and select AWTPermission
Targets name I select createRobot
The function field I have been leaving blank as I cant think what would apply here
Signed By in this window is also left blank
I then hit 'OK' and 'Done' and get a warning that there is no public key for the alias I've entered in the first step. I do a 'save as' and save my policyfile to the same directory as I put the certificate and the keystore generated from it.

This is not allowing me to run the applet from the webpage however and my limited understanding of this aspect of programming offers no clues as to what has gone wrong.

Ideas, thoughts, observations? If I havent explicitly mentioned something then I havent done it. My biggest suspect is the warning I recieve but I cant seem to find why its appearing

EDIT: Forgot to mention a step. I manually added to my jre\lib\security\java.security file the line 'policy.url.3=file:/C:/Testing/debugpolicy' since thats the path and policy filename I created during the above steps. I also just now managed to remove the warning I mentioned earlier, I'd been mixing up my alias' and gave the alias for the private keystore rather than the public one during policyfile creation, however I still encounter the same problems

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2024-10-29 20:29:03

如果小程序正确签名,则不需要策略文件,也不需要单独上传任何证书。正确签名的小程序将在加载之前在访问该小程序时提示用户获得许可。是否出现提示?

这是一个小演示。我写的演示了可信小程序的防御性加载。这就是我指的安全提示。

如果小程序经过开发人员的数字签名并受到最终用户的信任,则它应该能够截取屏幕截图。

如果小程序是可信的,您还可以尝试另一件事,只是作为实验 (1)。在小程序 init() 的早期,调用 System. setSecurityManager(null)。这将测试小程序是否具有信任,并清除给予小程序的“可信”安全管理器的最后残余。

如果有效,并且屏幕捕获成功,则表明存在错误或 Oracle 改变了对可信小程序默认功能的看法。

1) 不要在现实世界或生产环境中这样做。引用 Tom Hawtin 的话:

这个问题似乎给一些人留下了这样的印象:调用 System.setSecurityManager(null); 是可以的。 ...如果有人有任何疑问,更改小程序中的全局状态将影响同一进程中的所有小程序。清除安全管理器将允许任何未签名的小程序执行其喜欢的操作。请不要使用您希望任何人信任的证书来签署处理全局状态的代码。


编辑1:
这是该演示中使用的简单小程序的源代码。由于某种原因,当我最初上传它时,我认为来源不相关。 OTOH 现在有 3 个人出于某种原因要求查看消息来源。当我收到一轮学费时,我会将源代码上传到我的网站。同时,我会把它放在这里。

package org.pscode.eg.docload;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.security.*;

/** An applet to display documents that are JEditorPane compatible. */
public class DocumentLoader extends JApplet {
    JEditorPane document;

    @Override
    public void init() {
        System.out.println("init()");

        JPanel main = new JPanel();
        main.setLayout( new BorderLayout() );
        getContentPane().add(main);
        try {
            // It might seem odd that a sandboxed applet can /instantiate/
            // a File object, but until it goes to do anything with it, the
            // JVM considers it 'OK'.  Until we go to do anything with a
            // 'File' object, it is really just a filename.
            File f = new File(".");

            // set up the green 'sandboxed page', as a precaution..
            URL sandboxed = new URL(getDocumentBase(), "sandbox.html");
            document = new JEditorPane(sandboxed);
            main.add( new JScrollPane(document), BorderLayout.CENTER );
            // Everything above here is possible for a sandboxed applet

            // *test* if this applet is sandboxed
            final JFileChooser jfc =
                new JFileChooser(f); // invokes security check
            jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
            jfc.setMultiSelectionEnabled(false);

            JButton button = new JButton("Load Document");
            button.addActionListener( new ActionListener(){
                    public void actionPerformed(ActionEvent ae) {
                        int result = jfc.showOpenDialog(
                            DocumentLoader.this);
                        if ( result==JFileChooser.APPROVE_OPTION ) {
                            File temp = jfc.getSelectedFile();
                            try {
                                URL page = temp.toURI().toURL();
                                document.setPage( page );
                            } catch(Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } );
            main.add( button, BorderLayout.SOUTH );

            // the applet is trusted, change to the red 'welcome page'
            URL trusted = new URL(getDocumentBase(), "trusted.html");
            document.setPage(trusted);
        } catch (MalformedURLException murle) {
            murle.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (AccessControlException ace) {
            ace.printStackTrace();
        }
    }

    @Override
    public void start() {
        System.out.println("start()");
    }

    @Override
    public void stop() {
        System.out.println("stop()");
    }

    @Override
    public void destroy() {
        System.out.println("destroy()");
    }
}

If an applet is correctly signed, no policy file is required, nor is it required to separately upload any certificate. A correctly signed applet will prompt the user for permission when the applet is visited, before it loads. Does the prompt appear?

Here is a small demo. I wrote that demonstrates Defensive loading of trusted applets. That is the security prompt I am referring to.

If the applet is both digitally signed by the developer and trusted by the end user, it should be able to take a screen-shot.

There is one other thing you might try if the applet is trusted, just as an experiment (1). Early in the applet init(), call System.setSecurityManager(null). That will both test if the applet has trust, and wipe away the last remnants of the 'trusted' security manager given to applets.

And in the case that works, and it makes the screen capture successful, it suggests either a bug or Oracle changed their mind about the defaults of what a trusted applet could do.

1) Don't do this in a real world or production environment. To quote Tom Hawtin:

This question appears to have given some the impression that calling System.setSecurityManager(null); is okay. ... In case anyone has any doubts, changing global state in an applet will affect all applets in the same process. Clearing the security manager will allow any unsigned applet to do what it likes. Please don't sign code that plays with global state with a certificate you expect anyone to trust.


Edit 1:
Here is the source of the simple applet used in that demo. For some reason when I originally uploaded it, I decided the source was not relevant. OTOH 3 people have now asked to see the source, for one reason or another. When I get a round tuit I'll upload the source to my site. In the mean time, I'll put it here.

package org.pscode.eg.docload;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.security.*;

/** An applet to display documents that are JEditorPane compatible. */
public class DocumentLoader extends JApplet {
    JEditorPane document;

    @Override
    public void init() {
        System.out.println("init()");

        JPanel main = new JPanel();
        main.setLayout( new BorderLayout() );
        getContentPane().add(main);
        try {
            // It might seem odd that a sandboxed applet can /instantiate/
            // a File object, but until it goes to do anything with it, the
            // JVM considers it 'OK'.  Until we go to do anything with a
            // 'File' object, it is really just a filename.
            File f = new File(".");

            // set up the green 'sandboxed page', as a precaution..
            URL sandboxed = new URL(getDocumentBase(), "sandbox.html");
            document = new JEditorPane(sandboxed);
            main.add( new JScrollPane(document), BorderLayout.CENTER );
            // Everything above here is possible for a sandboxed applet

            // *test* if this applet is sandboxed
            final JFileChooser jfc =
                new JFileChooser(f); // invokes security check
            jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
            jfc.setMultiSelectionEnabled(false);

            JButton button = new JButton("Load Document");
            button.addActionListener( new ActionListener(){
                    public void actionPerformed(ActionEvent ae) {
                        int result = jfc.showOpenDialog(
                            DocumentLoader.this);
                        if ( result==JFileChooser.APPROVE_OPTION ) {
                            File temp = jfc.getSelectedFile();
                            try {
                                URL page = temp.toURI().toURL();
                                document.setPage( page );
                            } catch(Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } );
            main.add( button, BorderLayout.SOUTH );

            // the applet is trusted, change to the red 'welcome page'
            URL trusted = new URL(getDocumentBase(), "trusted.html");
            document.setPage(trusted);
        } catch (MalformedURLException murle) {
            murle.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (AccessControlException ace) {
            ace.printStackTrace();
        }
    }

    @Override
    public void start() {
        System.out.println("start()");
    }

    @Override
    public void stop() {
        System.out.println("stop()");
    }

    @Override
    public void destroy() {
        System.out.println("destroy()");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文