java.security.AccessControlException: доступ запрещен (решение java.net.SocketPermission smtp.gmail.com)

Я использую GlassFish Server 3.1 и почтовый API Java 1.4.5.

Сценарий: у меня есть апплет, который при нажатии отправляет сообщение электронной почты.

Отправка почты отлично работает в Netbeans AppletViewer, но превращается в ад при добавлении в браузер и попытке отправить оттуда электронное письмо.

Я часами читал о файлах политик, подписанных/неподписанных апплетах... и т.д.

Я пробовал использовать подписанный апплет (множество руководств по его подписанию, было довольно просто с использованием клавишных инструментов из java). Когда я запускаю его в браузере, он запрашивает разрешение, потому что это самозаверяющий сертификат, я даю ему разрешение, но он все равно выдает то же исключение.

Я также попытался изменить файл java.poilcy, добавив

разрешение java.net.SocketPermission "smtp.gmail.com:587", "прослушать, разрешить";

Но ничего.

Я знаю, что это исключение, потому что я активировал консоль Java в панели управления Java. Я действительно не знаю, что еще делать.

Вот код, который отправляет письмо:

    String host = "smtp.gmail.com";
    String from = *****;
    String pass = ******;
    Properties props = new Properties();
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", host);
    props.put("mail.smtp.user", from);
    props.put("mail.smtp.password", pass);
    props.put("mail.smtp.port", "587");
    props.put("mail.smtp.auth", "true");

    Session session = Session.getDefaultInstance(props, null);
    this.message = new MimeMessage(session);
    message.setFrom(new InternetAddress(from));

    InternetAddress toAddress = new InternetAddress(this.to);
    this.message.addRecipient(Message.RecipientType.TO, toAddress);

    this.message.setSubject(this.subject);

    this.message.setText(this.body);

    Transport transport = session.getTransport("smtp");
    transport.connect(host, from, pass);
    transport.sendMessage(this.message, this.message.getAllRecipients());
    transport.close();

person Chayemor    schedule 10.12.2012    source источник
comment
Вы уверены, что это апплет, а не GMail, отказывается от соединения?   -  person Andrew Thompson    schedule 10.12.2012
comment
Абсолютно уверен, потому что он отлично работает с AppletViewer (когда вы запускаете апплет в среде NetBeans, а не в браузере).   -  person Chayemor    schedule 11.12.2012


Ответы (4)


JApplet находится в «песочнице» сам по себе, с разрешениями, отличными от разрешений обычных приложений (приложения выполняются только тогда, когда пользователи делают это напрямую, следовательно, пользователь принимает последствия). JApplet запускается, когда браузер загружает его, не предоставляя пользователю никаких вариантов, поэтому, если вы хотите, чтобы ваш апплет был развернут и выполнен другими (когда апплет обращается к серверам, отличным от того, с которого он развернут), он должен быть подписанным (самоподписанным сертификатом или сертификатом, подписанным уполномоченной организацией, что обычно подразумевает оплату некоторых сборов), чтобы пользователь мог «принять» последствия использования указанного апплета, позволяя ему «выйти из песочницы».

По какой-то причине подписание его самостоятельным сертификатом с использованием keytolls и jarsigner у меня вообще не сработало. Несмотря на то, что когда я получил доступ к веб-странице, и браузер предупредил меня о выполнении апплета (предоставив мне возможность не выполнять его), и я принял это предупреждение, казалось, что JApplet не получает своих разрешений.

Мой парень предложил перенести класс электронной почты из «песочницы». Он решил эту проблему (благослови его!), переместив класс электронной почты (тот, который использует java mail api) на сервер, никаких проблем не возникло. Используя команду Front Controller для клиент-серверной архитектуры, все, что мне нужно было сделать, это реализовать свой класс Controller с кодом, который я разместил в начале вопроса, и отправить из моего апплета (при нажатии кнопки) http-запрос с адресом toEmailAddress, темой и телом моего сервлета.

Работает идеально.

person Chayemor    schedule 10.12.2012
comment
Привет - я рад, что вы решили это :). Как вы видели, было две проблемы: 1) апплет нужно было подписать и 2) доступ не был междоменным - person paulsm4; 10.12.2012
comment
подписание его самостоятельным сертификатом с использованием keytolls и jarsigner у меня тоже не сработало. Я использую jre7. Я пытаюсь прочитать файл, хранящийся на рабочем столе. - person Satish; 16.05.2013

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

person user207421    schedule 10.12.2012
comment
Я подписал апплет со следующими инструкциями: keytool -genkey -keystore akeystore -keyalg rsa -dname CN=Johanna Daniel, OU=Universidad, O=Universidad, L=Atlanta, ST=GA,C=NL -alias aks -validity 3600 -keypass password-storepass password // jarsigner -keystore akeystore -storepass password-keypass paswword -signedjar ArkanoidS.jar Arkanoid.jar aks Я также использовал параметр jarsigner -verify, чтобы убедиться, что мой ArkanoidS.jar был подписан. Именно эту банку (ПОДПИСАННУЮ) я добавил в свое веб-приложение и в тег html. Это все еще не работает. - person Chayemor; 10.12.2012
comment
@Joy Итак, вы выполнили одно из трех перечисленных мною условий. - person user207421; 10.12.2012
comment
Я не понимаю, какие условия не выполнены. Вы запросили, чтобы апплет был подписан либо несамоподписанным сертификатом, либо самозаверяющим сертификатом (в последнем случае пользователю будет предложено согласиться на выполнение апплета, даже если он был подписан с несамоподписанного сертификата). -авторизованный объект, то есть он имеет самозаверяющий сертификат). Я сделал все это, когда он был выполнен в браузере, он меня подсказал, и я принял условия и сказал ему выполнить это. Он продолжал получать одно и то же исключение. - person Chayemor; 11.12.2012

Несколько вещей, на которые стоит обратить внимание:

1) дважды проверьте и убедитесь, что подпись вашего апплета верна:

2) Посмотрите на crossdomain.xml:

3) Посмотрите на applet.policy

person paulsm4    schedule 10.12.2012

Распространяйте свою программу с помощью JNLP с подписью, это легко и решает такие ситуации.

Ознакомьтесь с руководствами по JNLP для вашей IDE и прочитайте это для получения дополнительной информации: http://docs.oracle.com/javase/6/docs/technotes/guides/jweb/deployment_advice.html

person Daniel De León    schedule 31.03.2013
comment
Я борюсь с той же ошибкой из запущенных приложений JNLP прямо сейчас. Работает нормально при запуске непосредственно из JAR, но при запуске JNLP происходит такой же сбой. :-( - person Brian Knoblauch; 31.07.2013
comment
Ваше приложение должно быть запущено из песочницы, чтобы получить доступ к большему количеству ресурсов, и есть еще один способ добиться этого, но он больше раздражает пользователя, который просто принимает подпись. - person Daniel De León; 01.08.2013