Я искал и искал, но не могу найти ответ на то, что кажется простым сценарием аутентификации.
У нас есть веб-приложение на Java, которое использует авторизацию на основе форм, предоставляемую Spring. Мы пытаемся получить доступ к этому приложению через наш портал, не требуя от пользователя ввода его учетных данных (SSO).
Портал имеет хранилище учетных данных, и мы можем успешно получить доступ к секретам удаленного веб-приложения на стороне сервера. Мы используем утилиту Apache HTTP Components для отправки запроса на вход в систему j_spring_security_check и успешно проводим аутентификацию. Ответ на это сообщение отправляет перенаправление 302 на домашнюю страницу приложения и устанавливает файл cookie с идентификатором сеанса.
Теперь нам нужно как-то отправить этот аутентифицированный сеанс обратно в браузер, и именно здесь у нас возникли проблемы. Простое перенаправление браузера на домашнюю страницу не работает - оно перенаправляет нас на страницу входа. Пересылка всех заголовков ответа обратно в браузер точно так, как они получены на стороне сервера, также не работает - все равно возвращается на страницу входа.
Итак, как мы аутентифицируем на стороне сервера и все еще можем загружать целевую страницу на стороне клиента?
Я относительно новичок в этом, поэтому я прошу прощения, если это глупый вопрос. Приветствуется любая помощь или совет относительно альтернативного подхода.
Примечания:
HttpComponent Код клиента:
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
// try to get the home page
HttpGet httpget = new HttpGet("http://<host>/<root>/home.action");
HttpResponse httpClientResponse = httpclient.execute(httpget);
HttpEntity entity = httpClientResponse.getEntity();
// check status and close entity stream
System.out.println("Login form get: " + httpClientResponse.getStatusLine());
EntityUtils.consume(entity);
// check cookies
System.out.println("Initial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
printCookies(cookies);
/*** Login ***/
HttpPost httppost = new HttpPost("http://<host>/<root>/j_spring_security_check");
// Prepare post parameters
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("j_username", getUserFromVault()));
nvps.add(new BasicNameValuePair("j_password", getPasswordFromVault()));
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClientResponse = httpclient.execute(httppost);
// copy response headers and determine redirect location
Header[] allHeaders = httpClientResponse.getAllHeaders();
System.out.println("Headers: ");
String location = "";
for (Header header : allHeaders) {
System.out.println(header);
if("location".equalsIgnoreCase(header.getName())) location = header.getValue();
response.addHeader(header.getName(), header.getValue());
}
// check response body
entity = httpClientResponse.getEntity();
System.out.println("Response content: " + httpClientResponse.getStatusLine());
System.out.println(EntityUtils.toString(entity)); // always empty
EntityUtils.consume(entity);
// check cookies
System.out.println("Post logon cookies:");
cookies = httpclient.getCookieStore().getCookies();
printCookies(cookies);
// populate redirect information in response
System.out.println("Redirecting to: " + locationHeaderValue);
response.setStatus(httpClientResponse.getStatusLine().getStatusCode()); // 302
// test if server-side get works for home page at this point (it does)
httpget = new HttpGet(location);
httpClientResponse = httpclient.execute(httpget);
entity = httpClientResponse.getEntity();
// print response body (all home content is loaded)
System.out.println("home get: " + httpClientResponse.getStatusLine());
System.out.println("Response content: " + httpClientResponse.getStatusLine());
System.out.println(EntityUtils.toString(entity));
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
Заголовки, возвращенные после успешного входа в систему на стороне сервера:
HTTP/1.1 302 Found
Date: Wed, 23 Feb 2011 22:09:03 GMT
Server: Apache/2.2.3 (CentOS)
Set-Cookie: JSESSIONID=6F98B0B9A65BA6AFA0472714A4C816E5; Path=<root>
Location: http://<host>/<root>/home.action
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Via: 1.1 PPWebFilter.<host>:80 (IronPort-WSA/7.0.0-825)
Connection: keep-alive
Заголовки из клиентского запроса и ответа:
Запрос:
GET /<root>/home.action HTTP/1.1
Host: <host>
Connection: keep-alive
Referer: http://localhost:10039/SCMViewer/TestLoginServlet?launchScm=Launch+SCM+servlet
Accept:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=FC8E823AB1A1545BE8518DB4D097E665
Ответ (перенаправить на логин):
HTTP/1.1 302 Found
Date: Wed, 23 Feb 2011 22:09:03 GMT
Server: Apache/2.2.3 (CentOS)
Location: http://<host>/<root>/security/login.action
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Via: 1.1 PPWebFilter.<host>:80 (IronPort-WSA/7.0.0-825)
Connection: keep-alive
В качестве теста мы написали небольшой взлом, который, кажется, работает, но слишком небезопасен, чтобы быть жизнеспособным:
- Внедрил форму в jsp, которая будет отправлять учетные данные для входа непосредственно в j_spring_security_check удаленного сайта.
- Написал метод сервлета для получения учетных данных из хранилища.
- Заполнил учетные данные на стороне клиента в скрытых полях формы и отправил форму через javascript.