Сохранить и повторно использовать запрос в фильтре сервлетов? - PullRequest
7 голосов
/ 28 декабря 2010

Я пишу фильтр OpenID на основе библиотеки JOID, чтобы позволить приложениям прозрачно проходить аутентификацию на нашем локальном сервере OpenID.Так как OpenID работает через перенаправления HTTP, я теряю исходный объект запроса в процессе, особенно если это POST с телом данных.Можно ли сохранить объект запроса таким образом, чтобы я мог повторно использовать его позже в транзакции, после того как пользователь прошел аутентификацию?Достаточно просто сохранить само тело сообщения, поскольку я могу достаточно легко сохранить URL-адрес запроса с помощью перенаправления туда и обратно (с помощью обратного URL-адреса OpenID).

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

Ответы [ 4 ]

7 голосов
/ 28 декабря 2010

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

String id = UUID.randomUUID().toString();
DataOfInterest data = new DataOfInterest(request);
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest");
map.put(id, data);
returnToUrl += "?token=" + URLEncoder.encode(id, "UTF-8");
// ...

А затем, когда он вернется, используйте HttpServletRequestWrapper, чтобы обернуть текущий запрос, в котором вы переопределяете getParameter() и консорциумов, чтобы вернуть интересующие исходные данные. Сделайте это в Filter.

String id = request.getParameter(token);
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest");
DataOfInterest data = map.remove(id);
chain.doFilter(new HttpServletRequestWithDataOfInterest(request, data), response);

HttpServletRequestWithDataOfInterest может выглядеть так:

public class HttpServletRequestWithDataOfInterest extends HttpServletRequestWrapper {

    private DataOfInterest data;

    public HttpServletRequestWithDataOfInterest(HttpServletRequest request, DataOfInterest data) {
        super(request);
        this.data = data;
    }

    public String getParameter(String name) {
        return data.getParameter(name);
    }

    public String[] getParameterValues(String name) {
        return data.getParameterValues(name);
    }

    // Etc, only when necessary.
}

Примечание. Любая очевидная обработка нулевой проверки и т. Д. Зависит от вас.

2 голосов
/ 28 декабря 2010

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

Вы можете проверить , как это реализовано в Spring Security ,

1 голос
/ 28 декабря 2010

Нет, вы не можете сохранить запрос.Но ваш фильтр может создать сеанс и добавить объект в область сеанса.Объекты, имеющие доступ к сеансу, могут использовать любой найденный объект.

0 голосов
/ 12 января 2011

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

Спасибо всем за их предложения.

...