Когда в статьях рассказывается о параметризованных запросах, останавливающих атаки SQL, они на самом деле не объясняют, почему это часто бывает так: «Это так, поэтому не спрашивайте, почему» - возможно, потому что они сами не знают. Верным признаком плохого педагога является тот, который не может признать, что он ничего не знает. Но я отвлекся. Когда я говорю, я понял, что совершенно понятно, что меня путают просто. Представьте себе динамический SQL-запрос
sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password
, поэтому простая инсталляция sql должна была просто ввести имя пользователя в качестве «OR 1 = 1». Это действительно сделало бы запрос sql:
sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password
В этом заявлении указывается, что все клиенты, где они являются, являются пустыми ('') или 1 = 1, что является логическим, приравнивая true. Затем он использует - чтобы прокомментировать остальную часть запроса. Таким образом, это будет просто распечатывать всю таблицу клиентов или делать с ней все, что вы захотите, если он войдет в систему, он войдет в систему с привилегиями первого пользователя, которые часто могут быть администратором.
Теперь параметризованные запросы делайте это по-другому, с кодом типа:
sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
parameters.add("User", username)
parameters.add("Pass", password)
, где имя пользователя и пароль являются переменными, указывающими на связанное введенное имя пользователя и пароль
. Теперь вы можете думать, что это ничего не меняет. Конечно, вы все равно могли бы просто ввести в поле имени пользователя что-то вроде Nobody OR 1 = 1 '-, эффективно выполнив запрос:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
И это похоже на действительный аргумент. Но вы ошибаетесь.
Способ работы с параметризованными запросами заключается в том, что sqlQuery отправляется как запрос, и база данных точно знает, что будет делать этот запрос, и только после этого он будет вставлять имя пользователя и пароли просто как ценности. Это означает, что они не могут выполнить запрос, потому что база данных уже знает, что будет делать запрос. Таким образом, в этом случае он будет искать имя пользователя «Nobody OR 1 = 1 '-» и пустой пароль, который должен выглядеть ложным.
Это не полное решение, хотя и вход валидация все равно потребуется, так как это не повлияет на другие проблемы, такие как атаки XSS, поскольку вы все равно можете поместить javascript в базу данных. Затем, если это зачитано на странице, оно будет отображать его как обычный javascript, в зависимости от какой-либо проверки валидации. Так что лучше всего по-прежнему использовать проверку ввода, но используя параметризованные запросы или хранимые процедуры, чтобы остановить любые атаки SQL.
После большого расследования я смог сделать некоторые значительные успехи.
Во-первых, вместо того, чтобы использовать JavaMail непосредственно, я рекомендую использовать Джакартская библиотека Commons Email . Это действительно упрощает проблему много!
код теперь:
HtmlEmail email = new HtmlEmail();
email.setHostName(mailserver);
email.setAuthentication(username, password);
email.setSmtpPort(port);
email.setFrom(fromEmail);
email.addTo(to);
email.setSubject(subject);
email.setTextMsg(textBody);
email.setHtmlMsg(htmlBody);
email.setDebug(true);
email.send();
Разговор о простом.
Однако существует все еще проблема. Версия HTML электронной почты работает отлично в Gmail, Hotmail, и т.д. Но это все еще правильно не отобразится в Outlook. Это всегда хочет отобразить текстовую версию, и я не уверен почему. Я подозреваю, что это - установка в Outlook, но я не могу найти его...
В дополнение к удалению эти html.setHeader("Content-Type", html.getContentType())
вызов, как уже предполагают, я заменил бы строку:
MimeMultipart content = new MimeMultipart();
… с:
MimeMultipart content = new MimeMultiPart("alternative");
… и удаление строки:
message.setHeader("Content-Type" , content.getContentType() );
конструктор MimeMultiPart по умолчанию мог вызывать проблемы с "многослойным/смешанным" типом контента.
При использовании многослойный/альтернативный, альтернативы заказаны тем, насколько верный они к оригиналу с лучшим представлением в последний раз. Однако клиенты обычно дают пользователям опцию отобразить простой текст, даже когда HTML присутствует. Вы уверены, что эта опция не включена в Outlook? Как делают другие агенты пользователя, как Thunderbird или Gmail, рассматривают Ваши сообщения?
кроме того, удостоверьтесь, что HTML правильно построен. Я проверил бы содержимое HTML с сервис проверки W3 , и возможно сохранил бы его в файл и просмотрел бы его с различными версиями IE также. Возможно, существует дефект, там заставляющий Outlook отступить к простому тексту.
html.setContent(htmlBody, "text/html");
html.setHeader("MIME-Version" , "1.0" );
html.setHeader("Content-Type" , html.getContentType() );
setContent
и setHeader("Content-Type", String)
делают то же самое - действительно ли возможно, что html.getContentType()
возвращает что-то другое, чем text/html
?
Расширение на основе комментария и @PhilLho & ответ @erickson (geez, я должен медленно вводить), используйте:
MimeMultipart content = new MimeMultipart("alternative")
Необходимо посмотреть на источник полученного сообщения: является многослойным/альтернативным Тип контента сообщения?
решение для workaroung решило перспективу 2003: Это сообщение использует набор символов, который не поддерживается интернет-сервисом. не отображается правильно.
Это могло произойти из-за кодирования. Большинство страниц HTML использует iso-8859-1 не попытка CP 1252, изменяющаяся
, Например, Ваш код:
message.setContent(sBuffer.toString(), "text/html");
Изменение это к:
message.setContent(new String(sBuffer.toString().getBytes(), "iso-8859-1"), "text/html; charset=\"iso-8859-1\"");
Это бросает новую контролируемую исключительную ситуацию: java.io. UnsupportedEncodingException, таким образом, необходимо объявить, что это брошено, или поймать его. iso-8859-1 поддерживается так, исключение никогда не будет выдаваться, если что-то не будет повреждено с Вашим rt.jar.
С уважением, Javeed javeed.mca@gmail.com
Измените это к:
message.setContent(new String(sBuffer.toString().getBytes(), "iso-8859-1"), "text/html; charset=\"iso-8859-1\"");
Набор Content Char. Должно быть:
message.setContent(sBuffer.toString(), "text/html;charset=iso-8859-1");