Настройка политик для апплета, встроенного в 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()");
}
}