Подтвердить что ты не робот

Как вы можете аутентифицировать использование Джерси-клиента на веб-сервере с поддержкой JAAS?

У меня есть следующий сценарий:

Сервер: Jetty (с настроенным JAAS)

Клиент: Джерси, вызванный через JUnit (через Maven)

У меня установлен JAAS на веб-сервере. Я использую клиентскую часть в качестве теста.

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

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

Я был бы очень признателен, если бы кто-нибудь мог показать мне пример, как это делается на стороне клиента с Джерси.

У меня есть следующий тестовый пример JUnit:

@Test
public void testLogin()
        throws IOException
{
    String URL_LOGIN = "http://localhost:9080/foo/auth.html";
    Client client = Client.create();

    String username = "me";
    String password = "me";

    final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password);
    client.addFilter(authFilter);
    client.addFilter(new LoggingFilter());

    WebResource webResource = client.resource(URL_LOGIN);
    // I even tried:
    // webResource.header("Authorization", "Basic " + "base64encoded_userid:password").type("application/xml");

    String page = webResource.post(String.class);

    System.out.println(page);
}

Обратите внимание:

1) http://localhost:9080/foo/auth.html - это страница, которую я должен видеть при успешном завершении.

2) Я действительно вижу вывод http://localhost:9080/foo/login.html.

3) Очевидно, что через браузер я могу успешно войти через страницу login.html.

Что мне, кажется, не хватает здесь?

4b9b3361

Ответ 1

С Basic auth вам вообще не нужно заходить на любую страницу входа. Если сервер настроен на использование Basic auth, вы можете делать запросы на любую защищенную страницу, если вы включаете основной заголовок auth в свои запросы. Фильтр Джерси позаботится об этом. Итак, если Basic auth действительно будет тем, что использует сервер, тогда ваш код должен работать.

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

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

Посмотрите, как выглядит login.html - он должен содержать форму. Если используется стандартная форма сервлета сервлета, URL-адрес действия этой формы должен быть "j_security_check", и должны быть два параметра формы: j_username и j_password. Если это так, вы можете попробовать что-то вроде следующего:

String URL_LOGIN = "http://localhost:9080/foo/j_security_check";
String URL_DATA = "http://localhost:9080/foo/auth.html";
Client client = Client.create();

// add a filter to set cookies received from the server and to check if login has been triggered
client.addFilter(new ClientFilter() {
    private ArrayList<Object> cookies;

    @Override
    public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
        if (cookies != null) {
            request.getHeaders().put("Cookie", cookies);
        }
        ClientResponse response = getNext().handle(request);
        // copy cookies
        if (response.getCookies() != null) {
            if (cookies == null) {
                cookies = new ArrayList<Object>();
            }
            // A simple addAll just for illustration (should probably check for duplicates and expired cookies)
            cookies.addAll(response.getCookies());
        }
        return response;
    }
});

String username = "me";
String password = "me";

// Login:
WebResource webResource = client.resource(URL_LOGIN);

com.sun.jersey.api.representation.Form form = new Form();
form.putSingle("j_username", username);
form.putSingle("j_password", password);
webResource.type("application/x-www-form-urlencoded").post(form);

// Get the protected web page:
webResource = client.resource(URL_DATA);
String response = webResource.get(String.class);

Я не тестировал это, поэтому, возможно, будут опечатки или ошибки.

Ответ 2

Я не использую Джерси, но это не проблема Джерси как таковая.

Во-первых, вы должны использовать авторизацию FORM или BASIC; если это не обычная разработка, я сомневаюсь, что вы используете "форму с базовой аутентификацией".

Если вы используете базовую проверку подлинности, то все довольно просто (хотя и неэффективно): аутентификация BASIC не имеет статуса, и вы должны отправить HTTP-заголовок Authorization: Basic xxxx на КАЖДЫЙ запрос.

Если вы используете FORM login, все будет немного более привлекательным. По каждому запросу вы должны отправить идентификатор сеанса (хранящийся в Cookie или используя переписывание URL-адресов). Если вы его не отправите, или если связанный сеанс недействителен (поскольку он истек, например), сервер отправит 302 (перенаправление) и форму входа. Затем вы должны выполнить отправку FORM POST по URL-адресу, указанному в форме с именем пользователя и паролем в качестве параметров. Если аутентификация прошла успешно, сервер отправит ответ на исходный запрос (и новый идентификатор сеанса). В этом случае программный запрос должен иметь возможность

  • 1. Обрабатывайте файлы cookie (если вы не принудительно переписываете URL-адрес, что маловероятно)
  • 2. Обнаружить, когда они возвратят форму запроса 302 и войти в запрос, и заполнить требуемый пост формы до их продолжения.
Это верно для любого HTTP-вызова (AJAX, REST и т.д.) И обратите внимание, что тот факт, что ваш сервер использует JAAS или другой механизм авторизации и авторизации, не имеет никакого отношения: это проблема управления сеансом.

В качестве альтернативы, специальное решение для Джерси доступно путем перехвата вызовов:

Как получить журналы Джерси на сервере?

Ответ 3

Авторизация для JAAS:

    String URL_DATA = "http://localhost:9080/foo/auth.html";
    Client client = Client.create();

    String username = "me";
    String password = "me";

    client.addFilter(new HTTPBasicAuthFilter(username, password));

    // Get the protected web page:
    WebResource webResource = client.resource(URL_DATA);
    String response = webResource.get(String.class);
    System.out.println(response);

Ответ 4

Для меня эти изменения решили проблему:

String URL_LOGIN = "http://localhost:9080/foo/j_security_check";
String URL_DATA = "http://localhost:9080/foo/auth.html";
Client client = Client.create();

// add a filter to set cookies received from the server and to check if login has been triggered
client.addFilter(new ClientFilter() {
    private ArrayList<Object> cookies;

    @Override
    public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
        if (cookies != null) {
            request.getHeaders().put("Cookie", cookies);
        }
        ClientResponse response = getNext().handle(request);
        // copy cookies
        if (response.getCookies() != null) {
            if (cookies == null) {
                cookies = new ArrayList<Object>();
            }
            // A simple addAll just for illustration (should probably check for duplicates and expired cookies)
            cookies.addAll(response.getCookies());
        }
        return response;
    }
});

String username = "me";
String password = "me";


// Get the protected web page: (this will make the server know that someone will try to access the protected resource)
WebResource  webResource = client.resource(URL_DATA);
String response = webResource.get(String.class);


// Login:
webResource = client.resource(URL_LOGIN);

com.sun.jersey.api.representation.Form form = new Form();
form.putSingle("j_username", username);
form.putSingle("j_password", password);
webResource.type("application/x-www-form-urlencoded").post(form);


// Get the protected web page: (this time the service will return the data)
webResource = client.resource(URL_DATA);
response = webResource.get(String.class);