Авторизация на сайте
Цитата У меня стоит задача такая, взять данные у одного сайта(нашего корпоративного, не с интернета, но это думаю не важно), к базе не имею доступа и сказали не дадут, хотите парсите со страницы. В общем в этой теме впервые, раньше парсила только с xml или целую html страницу полностью))) А сейчас нужно сначала пройти авторизацию, потом ввести в поисковик id нужного человека и оттуда вытаскивать результат. Два дня вот копаюсь как можно реализовать. Нашла несколько возможных вариантов. С использованием httpclient, но мне выдает страницу ввода пароли, дальше не идет. То есть ввожу страницу после ввода пароли и имени пользователя, но опять же направляют на страницу с запросом пароля. Помогите пожалуйста.
Там мне посоветовали:
Цитата Какой тип авторизации на сайте? Если не BASIС, то вероятнее всего нужно все-таки использовать метод POST и еще более вероятно, что при этом используется протокол HTTPS. Неплохо бы задать эти вопросы тем, кто вам поставил такую задачу. (25 Июн 1:39)a_gura не забывайте про Encode/Decode данных, при GET и POST запросах, а так же при получении данных . А так согласен с @a_gura — запросы на авторизацию в большинстве случаев это POST запросы
Начала читать книгу Jeff Heaton «HTTP Programming Recipes for Java Bots», разбиралась в примерах полной уверенностью что это то что мне нужно. Так вот по этому примеру я сделала: CookieUtility и FormUtility я взяла из книги CookieUtility.java
import java.net.*; import java.util.*; public class CookieUtility < // Map that holds all of the cookie values. private Mapmap = new HashMap(); public Map getMap() < return this.map; >/** * Load any cookies from the specified URLConnection * object. Cookies will be located by their Set-Cookie * headers. Any cookies that are found can be moved to a * new URLConnection class by calling saveCookies. * * @param http * The URLConnection object to load the cookies from. */ public void loadCookies(URLConnection http) < String str; int n = 1; do < str = http.getHeaderFieldKey(n); if ((str != null) && str.equalsIgnoreCase("Set-Cookie")) < str = http.getHeaderField(n); StringTokenizer tok = new StringTokenizer(str, "="); String name = tok.nextToken(); String value = tok.nextToken(); this.map.put(name, value); >n++; > while (str != null); > /** * Once you have loaded cookies with loadCookies, you can * call saveCookies to copy these cookies to a new HTTP * request. This allows you to easily support cookies. * * @param http * The URLConnection object to add cookies to. */ public void saveCookies(URLConnection http) < StringBuilder str = new StringBuilder(); Setset = this.map.keySet(); for (String key : set) < String value = this.map.get(key); if (str.length() >0) < str.append("; "); >str.append(key + "=" + value); > http.setRequestProperty("Cookie", str.toString()); > >
FormUtility.java
import java.io.*; import java.net.*; import java.util.*; public class FormUtility < // The charset to use for URL encoding. should always be UTF-8. private final static String encode = "UTF-8"; private static Random random = new Random(); //Generate a boundary for a multipart form. public static String getBoundary() < return "---------------------------" + randomString() + randomString() + randomString(); >/** * Parse a URL query string. Return a map of all of the * name value pairs. * * @param form * The query string to parse. * @return A map of name-value pairs. */ public static Map parse(String form) < Mapresult = new HashMap(); StringTokenizer tok = new StringTokenizer(form, "&"); while (tok.hasMoreTokens()) < String str = tok.nextToken(); StringTokenizer tok2 = new StringTokenizer(str, "="); if (!tok2.hasMoreTokens()) < continue; >String left = tok2.nextToken(); if (!tok2.hasMoreTokens()) < left = encode(left); result.put(left, null); continue; >String right = tok2.nextToken(); right = encode(right); result.put(left, right); > return result; > private static String encode(String str) < try < return URLEncoder.encode(str, encode); >catch (UnsupportedEncodingException e) < return str; >> protected static String randomString() < return Long.toString(random.nextLong(), 36); >/* * The boundary used for a multipart post. This field is * null if this is not a multipart form and has a value if * this is a multipart form. */ private String boundary; private OutputStream os; private boolean first; /** * Prepare to access either a regular, or multipart, form. * * @param os * The stream to output to. * @param boundary * The boundary to be used, or null if this is * not a multipart form. */ public FormUtility(OutputStream os, String boundary) < this.os = os; this.boundary = boundary; >//Add a file to a multipart form. public void add(String name, File file) throws IOException < if (this.boundary != null) < boundary(); writeName(name); write("; filename=\""); write(file.getName()); write("\""); newline(); write("Content-Type: "); String type = URLConnection.guessContentTypeFromName(file.getName()); if (type == null) < type = "application/octet-stream"; >writeln(type); newline(); byte[] buf = new byte[8192]; int nread; InputStream in = new FileInputStream(file); while ((nread = in.read(buf, 0, buf.length)) >= 0) < this.os.write(buf, 0, nread); >newline(); > > // Add a regular text field to either a regular or multipart form. public void add(String name, String value) throws IOException < if (this.boundary != null) < boundary(); writeName(name); newline(); newline(); writeln(value); >else < if (!this.first) < write("&"); >write(encode(name)); write("="); write(encode(value)); > this.first = false; > //Complete the building of the form. public void complete() throws IOException < if (this.boundary != null) < boundary(); writeln("--"); this.os.flush(); >> // Generate a multipart form boundary. private void boundary() throws IOException < write("--"); write(this.boundary); >// Create a new line by displaying a carriage return and linefeed. private void newline() throws IOException < write("\r\n"); >// Write the specified string, without a carriage return and line feed. private void write(String str) throws IOException < this.os.write(str.getBytes()); >// Write the name element for a multipart post. private void writeName(String name) throws IOException < newline(); write("Content-Disposition: form-data; name=\""); write(name); write("\""); >//Write a string, with a carriage return and linefeed.270 HTTP Programming Recipes for Java Bots protected void writeln(String str) throws IOException < write(str); newline(); >>
И собственно мой парсер Parser.java
package parser; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; public class Parser < private CookieUtility cookies = new CookieUtility(); private boolean login(String username, String password) throws IOException < URL url = new URL("http://10.10.10.90/Account/Login.aspx?ReturnUrl=%2fdefault.aspx"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setInstanceFollowRedirects(false); http.setDoOutput(true); OutputStream os = http.getOutputStream(); FormUtility form = new FormUtility(os, null); form.add("login_name", URLEncoder.encode(username)); form.add("login_password", URLEncoder.encode(password)); form.complete(); http.getInputStream(); cookies.loadCookies(http); return (cookies.getMap().containsKey("ASP.NET_SessionId")); >public String downloadPage(URL url, int timeout) throws IOException < StringBuilder result = new StringBuilder(); byte buffer[] = new byte[8192]; URLConnection http = url.openConnection(); http.setConnectTimeout(10000); InputStream s = http.getInputStream(); int size = 0; do < size = s.read(buffer); if (size != -1) result.append(new String(buffer, 0, size)); >while (size != -1); return result.toString(); > public void process(String username, String password) throws IOException < if(login(username,password)) < URL url = new URL("http://10.10.10.90/default.aspx"); String buffer = downloadPage(url,10000); System.out.println(buffer); >else < System.out.println("Authorization error.."); >> public static void main(String args[]) < try < Parser p = new Parser(); p.process("d.aim", "432545"); >catch (Exception e) < e.printStackTrace(); >> >
Вроде все есть, ловим куки, передаем POST запрос, но все равно получаю страницу с запросом авторизации. Может дело в том что авторизация на этом сайте реализована на джаваскрипте? Но вроде если читать ту вышеупомянутую книгу это не должно быть проблемой. Так в чем я ошиблась? Что сделала не так? Или может я вообще неправильно делаю? Помогите решить, уже не первую неделю бьюсь с этой авторизацией:(
Как написать сайт на джаве с паролем
Вначале создадим на сервере MySQL пустую базу данных, которую назовем store и с которой мы будет работать в приложении на Java. Для создания базы данных применяется выражение SQL:
CREATE DATABASE store;
Его можно выполнить либо из консольного клиента MySQL Command Line Client, либо из графического клиента MySQL Workbench, которые устанавливются вместе с сервером MySQL. Подробнее про создание базы данных можно прочитать в статье Создание и удаление базы данных.
Для подключения к базе данных необходимо создать объект java.sql.Connection . Для его создаия применяется метод:
Connection DriverManager.getConnection(url, username, password)
Метод DriverManager.getConnection в качестве параметров принимает адрес источника данных, логин и пароль. В качестве логина и пароля передаются логин и пароль от сервера MySQL. Адрес локальной базы данных MySQL указывается в следующем формате: jdbc:mysql://localhost/название_базы данных
Пример создания подключения к созданной выше локальной базе данных store:
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/store", "root", "password");
После завершения работы с подключением его следует закрыть с помощью метода close() :
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/store", "root", "password"); // работа с базой данных connection.close();
Либо мы можем использовать конструкцию try :
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/store", "root", "password")) < // работа с базой данных >
Возможные проблемы с часовыми поясами и SSL
При подключении к базе данных MySQL мы можем столкнуться с рядом проблем. Например, определим следующий код подключения:
import java.sql.Connection; import java.sql.DriverManager; public class Program < public static void main(String[] args) < try< String url = "jdbc:mysql://localhost/store"; String username = "root"; String password = "password"; Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance(); try (Connection conn = DriverManager.getConnection(url, username, password))< System.out.println("Connection to Store DB succesfull!"); >> catch(Exception ex) < System.out.println("Connection failed. "); System.out.println(ex); >> >
Даже если указаны правильно адрес базы данных, логин, пароль, мы все равно можем столкнуться с ошибками:

Из консольного вывода видно, что проблема заключается с SSL и часовым поясом. Чтобы решить данную проблему, необходимо указать в адресе подключения часовой пояс бд и параметры для использования ssl. В частности, я указываю, что SSL не будет использоваться и что часовым поясом будет московский часовой пояс:
String url = "jdbc:mysql://localhost/store?serverTimezone=Europe/Moscow&useSSL=false";
Параметры подключения указываются после вопросительного знака после названия базы данных. Параметр serverTimezone указывает на название часового пояса сервера бд. В данном случае «Europe/Moscow», cписок всех допустимых названий часовых поясов можно найти на странице https://gist.github.com/kinjal/9105369. И параметр useSSL=false указывает, что SSL не будет применяться.
Файлы конфигурации
Мы можем определить все данные для подключения непосредственно в программе. Однако что если какие-то данные были изменены? В этом случае потребуется перекомпиляция приложения. Иногда это не всегда удобно, например, отсутствует досуп к исходникам, или перекомпиляция займет довольно продолжительное время. В этом случае мы можем хранить настройки в файле.
Так, создадим в папке программы новый текстовый файл database.properties , в котором определим настройки подключения:
url = jdbc:mysql://localhost/store?serverTimezone=Europe/Moscow&useSSL=false username = root password = password
Загрузим эти настройки в программе:
import java.sql.*; import java.nio.file.*; import java.io.*; import java.util.*; public class Program < public static void main(String[] args) < try< Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance(); try (Connection conn = getConnection())< System.out.println("Connection to Store DB succesfull!"); >> catch(Exception ex) < System.out.println("Connection failed. "); System.out.println(ex); >> public static Connection getConnection() throws SQLException, IOException < Properties props = new Properties(); try(InputStream in = Files.newInputStream(Paths.get("database.properties")))< props.load(in); >String url = props.getProperty("url"); String username = props.getProperty("username"); String password = props.getProperty("password"); return DriverManager.getConnection(url, username, password); > >
Авторизация на сайте
Данный пример не претендует на звание идеального метода защиты, но все же обойти его будет достаточно трудно. Представим следующее: у вас есть закрытый сайт «для своих» и вы не хотите чтобы туда заходили всякие нехорошие личности. В этом нам помогут сессии. Пароли и логины будем хранить в таблице mysql.
На первой странице index.php делаем форму для ввода данных:
Думаю здесь пояснять ничего не нужно. Идем дальше: Сначала краткое пояснение. Мы создаем функцию проверки пользователя check(). У нас есть база данных my_site, содержащая поля id, name и pass, где name и pass — логин и пароль пользователя соответственно. Функция пропускает только тех, кто указал верный логин и пароль в форме ($name, $pass) на входе, потом эти переменные сохраняются в сессию, следовательно, пока сессия жива пользователь может заходить на ваш сайт без авторизации. Даже указав другой верный логин и пароль, он будет авторизирован под указанным ранее логином.
Предполагается, что соединение с базой mysql уже произведено и база данных выбрана.
function check()
if (empty($pass)||empty($name))
error("Не указан логин или пароль");
$sql = "select * from my_site where login='".$name."'";
if ($show = mysql_query($sql))
$a = mysql_fetch_array($show);
if ($a['pass']!=$pass) error("Не верное сочетание логин - пароль");
>
else session_register("name","pass");
>
>
else error("Ошибка запроса к базе данных");
>
>
?>
Начнем пояснения с первой строки.
if (empty($pass)||empty($name))
error("Не указан логин или пароль");
function error($er)
echo $er;
exit(0);
>
?>
$sql="select pass from mysite where login='".$name."'";
if ($show=mysql_query($sql))
$a=mysql_fetch_array($show);
f ($a['pass']!=$pass)
error("Не верное сочетание логин - пароль");
else
session_register("name","pass");
>
else
error("Ошибка запроса к базе данных");
>
?>
Если есть ошибка в запросе к базе mysql, то мы опять же выводим ошибку пользователю.
Итак, вначале каждой страницы, к которой нужно запретить доступ посторонним пишем:
session_start();
/* эта функция открывающая или продолжающая работу с сессиями. Она должна быть задана в самом начале страницы до отправки заголовка страницы. */
check(); //наша функция проверки.
?>
Теперь проверим логику скрипта. Если человек не заполняет одно из полей и нажимает кнопку «вход», то перейдя на страницу index2.php он получит надпись «Ошибка: Не указан логин или пароль».
Если он указывает неверный логин или пароль, то ему выпадает «Ошибка: Не верное сочетание логин — пароль».
Если же он все указывает верно, то попадет на страницу index2.php где вы храните свои тайны. За счет того, что логин и пароль записываются в сессию, юзер может бродить по вашему сверх тайному сайту авторизировавшись только один раз.
Нельзя заходить на сайт под разными именами.
Если человек раз зашел на сайт, то с его компьютера можно посещать этот сайт еще в течении некоторого времени (пока жива сессия), что не очень хорошо, если ты работаешь из Интернет салона.
Как включить JavaScript в вашем веб-браузере
В настоящее время почти все веб-страницы используют JavaScript, скриптовый язык программирования, который работает на веб-браузере посетителя. Это делает веб-страницы более функциональными, а если по каким-либо причинам JavaScript отключен, содержание или функциональность веб-страницы может быть ограничена или вовсе не возможна. Здесь вы можете найти инструкции о том, как включить (активировать) JavaScript в пяти наиболее распространенных веб-браузерах.
Если вы веб-разработчик, посмотрите инструкции о том как использовать тег в коде вашей интернет-страницы.
Google Chrome
- В меню браузера нажмите кнопку «Customize and control Google Chrome» и выберите пункт «Settings».
- На странице «Settings» нажмите ссылку «Show advanced settings. «
- Под пунктом «Privacy» нажмите на кнопку «Content settings. «.
- Когда диалоговое окно откроется, посмотрите на секцию «JavaScript» и поставьте галочку «Allow all sites to run JavaScript (recommended)».
- Нажмите кнопку «OK», чтобы закрыть окно.
- Закройте вкладку «Settings».
- Нажмите на кнопку «Reload this page» для обновления страницы.
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
Mozilla Firefox
- В адресной строке введите about:config и нажмите Enter.
- Нажмите «Я буду осторожен, обещаю», если появится предупреждающее сообщение.
- В поле поиска найдите javascript.enabled.
- Переключите настройку «javascript.enabled» (щелкните правой кнопкой мыши и выберите «Переключить» или дважды щелкните настройку), чтобы изменить значение с «false» на «true».
- Нажмите кнопку «Обновить текущую страницу» в веб-браузере, чтобы обновить страницу.
- 1.
- 2.
- 3.
- 4.
- 5.
Apple Safari
- В меню веб-браузера нажмите на кнопку «Edit» и выберите «Preferences».
- В окне «Preferences» выберите вкладку «Security».
- На вкладке «Security» в разделе «Web content» поставьте галочку «Enable JavaScript».
- Нажмите на кнопку «Reload the current page» в веб-браузере, что бы обновить страницу.
- 1.
- 2.
- 3.
- 4.
Opera
- 1. Нажмите на значок Opera «Меню», а затем «Настройки».
- 2. Нажмите «Веб-сайты», а затем выберите «Разрешить всем сайтам запускать JavaScript (рекомендуется)».
- 3. Нажмите кнопку «Обновить» в веб-браузере, чтобы обновить страницу.
1. 2. 3.
Internet Explorer
- В меню веб-браузера нажмите «Tools» и выберите пункт «Internet Options».
- В разделе «Internet Options» выберите вкладку «Security».
- На вкладке «Security» нажмите кнопку «Custom level. «.
- После открытия диалогового окна «Security Settings — Internet Zone», посмотрите раздел «Scripting».
- В разделе «Active Scripting» выберите пункт «Enable».
- После появления всплывающего окна «Warning!» в котором спрашивается «Are you sure you want to change the settings for this zone?» нажмите кнопку «Yes».
- В окне «Internet Options» нажмите кнопку «OK», что бы закрыть его.
- Нажмите на кнопку «Refresh» в веб-браузере, чтобы обновить страницу.
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
Инструкции для разработчиков
Вы можете использовать ссылку на этот сайт, что бы рассказать пользователям у которых отключен Javascript о том, как включить Javascript в пяти наиболее распространенных веб-браузерах. Вы можете использовать приведенный ниже код и изменить его в соответствии с вашими нуждами.
- Инструкции для вашего браузера помещаются в верхнюю часть страницы
- Все изображения кликабельны, для удобства просмотра в натуральном размере
- Инструкции для разработчиков размещены в самом низу страницы и не мешают обычным пользователям.
О проекте
Программирование, проектирование, тестирование, получение обратной связи с пользователями и написание материалов для этого сайта сделали Тони Подманиски, Пол Ирландских и Джереми Хилл. Мы хотели бы поблагодарить всех тех, кто помогал и содействовал нам любым способом. Надеемся эта страница окажется полезной для вас и ваших пользователей.