Настройка политик для апплета, встроенного в HTML

Я разработал апплет, чтобы сделать снимок экрана и сохранить его на компьютере пользователя с помощью класса 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 в каталог сервера, где размещены соответствующие страницы.

Однако: когда я затем использовал policytool для создания нового файла политики на одном из компьютеров, чтобы протестировать установку, я все еще не могу выполнить апплет из HTML. Я получаю Java.Security.AccessControlException Acess Denied java.awt.AWTPermission createRobot.

Я скорее подозреваю, что это шаг политики, который идет неправильно, поэтому я обрисую в общих чертах шаги, которые я предпринял: я загружаю сертификат на локальный компьютер и генерирую хранилище ключей из него, я запускаю 'policytool' из этого каталога через командную строку, которую я добавляю каталог на локальной машине, где хранится хранилище ключей и мой сертификат. Затем я нажимаю кнопку добавления политики и ввожу псевдоним SignedBy. Затем добавляем разрешения и выбираем имя цели AWTPermission. Я выбираю createRobot. Поле функции, которое я оставляю пустым, так как я не могу думать, что будет применяться здесь, подписано в этом окне, также остается пустым. нажмите "ОК" и "Готово" и получите предупреждение об отсутствии открытого ключа для псевдонима, который я ввел на первом шаге. Я делаю "сохранить как" и сохраняю свой файл политики в том же каталоге, в котором я поместил сертификат и сгенерированное из него хранилище ключей.

Однако это не позволяет мне запускать апплет с веб-страницы, и мое ограниченное понимание этого аспекта программирования не дает никаких подсказок относительно того, что пошло не так.

Идеи, мысли, наблюдения? Если я не упомянул что-то явно, то я этого не сделал. Моим самым большим подозреваемым является предупреждение, которое я получаю, но я не могу понять, почему оно появляется

РЕДАКТИРОВАТЬ: забыл упомянуть шаг. Я вручную добавил в свой файл jre\lib\security\java.security строку 'policy.url.3=file:/C:/Testing/debugpolicy', поскольку это путь и имя файла политики, которые я создал на предыдущих этапах. Мне также только что удалось удалить предупреждение, о котором я упоминал ранее, я смешивал свой псевдоним и давал псевдоним для личного хранилища ключей, а не для общего, при создании файла политики, однако я все еще сталкиваюсь с теми же проблемами.

1 ответ

Решение

Если апплет правильно подписан, файл политики не требуется, и при этом не требуется отдельно загружать какой-либо сертификат. Правильно подписанный апплет запросит у пользователя разрешение при посещении апплета до его загрузки. Появляется ли подсказка?

Вот небольшая демонстрация. Я написал, что демонстрирует защитную загрузку доверенных апплетов. Это подсказка безопасности, о которой я говорю.

Если апплет имеет цифровую подпись разработчика и доверяется конечному пользователю, он должен быть в состоянии сделать снимок экрана.

Есть еще одна вещь, которую вы можете попробовать, если апплет является доверенным, как эксперимент (1). В начале апплета init(), вызов System.setSecurityManager(null), Это будет одновременно проверять, доверяет ли апплет, и стирает последние остатки "доверенного" менеджера безопасности, переданного апплетам.

И в случае, если это работает, и это делает снимок экрана успешным, это предлагает или ошибку, или Oracle передумал о настройках по умолчанию того, что мог сделать доверенный апплет.

1) Не делайте этого в реальном мире или производственной среде. Цитировать Тома Хотина:

Этот вопрос, похоже, создал впечатление 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()");
    }
}
Другие вопросы по тегам