Как вы можете аутентифицироваться, используя клиент Jersey на веб-сервере с поддержкой JAAS? - PullRequest
11 голосов
/ 13 марта 2012

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

Сервер: 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.

Чего мне здесь не хватает?

Ответы [ 5 ]

22 голосов
/ 14 марта 2012

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

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

Чтобы проверка подлинности на основе форм работала, вам необходимо отправить запрос с данными формы, включая имя пользователя и пароль, для входа в систему, а затем установить файлы 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);

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

10 голосов
/ 13 марта 2012

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

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

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

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

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

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

3 голосов
/ 20 августа 2014

Авторизация для 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);
2 голосов
/ 27 октября 2018

Чтобы получить доступ к конечной точке отдыха из проверки подлинности на основе формы Необходимо зарегистрировать фильтр проверки подлинности формы в клиенте JAX-RS Jersey. Один полезный класс фильтров приведен в следующей ссылке на git hub.

https://github.com/imixs/imixs-melman/blob/master/src/main/java/org/imixs/melman/FormAuthenticator.java

используйте FormAuthenticator.java в своем проекте, а в клиенте Rest Jersey выполните следующее:

// Constructor of jersey Rest client
public RestClass(String username, String password)
{
    private WebTarget webTarget;
    private Client client;

    private static final String BASE_URI = "http://localhost:8080/SampleRest/webresources";

    client = javax.ws.rs.client.ClientBuilder.newClient();
    client.register(new FormAuthenticator(BASE_URI, user,  password));

    webTarget = client.target(BASE_URI).path("restpath");
}

И все отлично работает. Я использовал это, и эта проблема решена. JAX-RS API должен предоставить этот аутентификатор в своем выпуске.

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

as RestClient rs = new RestClient(username, password);

** Класс приложения должен зарегистрировать RolesAllowedDynamicFeature, чтобы роли вступили в силу ** MyApplication.java в веб-проекте, в котором находится класс Rest и FormAuthenticator.java - пакет отдыха

@ApplicationPath("webresources")

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        packages("entity.service");
        packages("rest");
        register(RolesAllowedDynamicFeature.class);
    }
}
1 голос
/ 30 апреля 2013

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

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...