Как Seam 3 обрабатывает функцию «перенаправить на захват» после входа в систему? - PullRequest
2 голосов
/ 15 февраля 2012

Вот мои варианты использования.

У меня есть страница входа, которая /public/login.xhtml. Все остальные мои страницы должны войти в систему, прежде чем их достичь. Они находятся в каталоге /pages/.

Я хочу это:

  1. Если мой пользователь получает доступ к http://host/myapp/pages/*, он перенаправляет его сначала на страницу входа, а затем на URL, который он впервые ввел.
  2. Если мой пользователь имеет доступ к http://host/myapp/, он перенаправляет его сначала на страницу входа, а затем на /pages/home.xhtml.
  3. Если мой пользователь имеет доступ к http://host/myapp/public/login.xhtml, он перенаправляет его сначала на страницу входа, а затем на /pages/home.xhtml.
  4. Если мой пользователь имеет доступ к http://host/myapp/public/login.xhtml и уже вошел в систему, он перенаправляется на /pages/home.xhtml.

Что сейчас работает?

С Seam 3 (v3.1.0.Final) и модулем Security + Faces мой сценарий использования n ° 1 работает автоматически с:

@ViewConfig
public interface PagesConfig {
    static enum Pages {
        @ViewPattern("/pages/*")
        @LoginView("/public/login.xhtml")
        @LoggedIn
        LOGGED_IN_PAGES,
    }
}

Моя проблема в том, что Я не понимаю, как работает Seam, чтобы сделать это перенаправление в «представление захвата» .

С Seam 2 это было легко понять, в components.xml у нас было

<event type="org.jboss.seam.security.notLoggedIn">
    <action execute="#{redirect.captureCurrentView}" />
</event>
<event type="org.jboss.seam.security.loginSuccessful">
    <action execute="#{redirect.returnToCapturedView}" />
</event>

Итак, мы захватили события notLoggedIn и loginSuccessful для обработки этого с помощью redirect компонента.

В Seam 3 я не нашел эту конфигурацию: кажется, что @Observes LoggedInEvent ничего не существует, и Redirect класса нет ...

Точка n ° 2 достигается с помощью этого файла /index.htm:

<html><head>
    <meta http-equiv="Refresh" content="0; URL=pages/home.xhtml">
</head></html>

Но для моей точки № 3 я пробовал решения, которые не работают полностью.

Сначала я попробовал это в login.xhtml:

<f:metadata>
    <s:viewAction action="#{loginAction.redirectToHome}" if="#{identity.loggedIn}" immediate="true" />
</f:metadata>

И с или без onPostback="true", после того, как я войду в систему, я все еще на странице входа в систему с таким сообщением об ошибке (дважды): " Невозможно найти соответствующий случай навигации с from-view-id« / public /login.xhtml »для действия« # {identity.login} »с результатом« success ». ". Только если я теперь снова получу доступ к http://host/myapp/public/login.xhtml, мой viewAction перенаправит меня в дом.

Я также пробовал это правило навигации в faces-config.xml:

<navigation-rule>
    <from-view-id>/public/login.xhtml</from-view-id>

    <navigation-case>
        <if>#{identity.loggedIn}</if>
        <to-view-id>/pages/home.xhtml</to-view-id>
        <redirect />
    </navigation-case>
</navigation-rule>

Но тогда мой вариант использования № 1 был отключен: каждый раз, когда я входил в систему, меня перенаправляли в дом.

Наконец, для моей точки n ° 4 , s:viewAction выполняет свою работу.


Так кто-нибудь знает лучшие практики для правильной обработки этих 4-х вариантов использования (которые я считаю наиболее распространенными), особенно пункт № 3?

Ответы [ 2 ]

1 голос
/ 16 февраля 2012

Вариант использования №. 1 SeamFaces сохраняет первоначально запрошенный viewId в пользовательском сеансе и затем перенаправляет его в этот вид после успешного входа в систему.Это делается путем перехвата навигации от кнопки входа в Seam Security, и запускает PostLoginEvent с данными, хранящимися в SessionMap.

Вариант использования № 2 - отличное решение с перенаправлением!Вы также можете сделать это с помощью @ UrlMapping в вашем ViewConfig .

Вариант использования № 3 - ваше решение viewAction должно работать, но я считаю, что вы сталкиваетесь с SEAMFACES-179.Есть несколько решений, которые вы можете использовать:

1) В вашем методе входа в систему вы можете манипулировать картой видения, хранящейся на лицах шва, как показано в этом gist - (эторешение предоставлено Cody Lerum )

2) Используйте PrettyFaces , чтобы перехватить запрос на просмотр входа в систему и перенаправить вас, если вы не вошли в систему.

0 голосов
/ 23 февраля 2012

Наконец вот что я сделал.

<f:metadata>
    <s:viewAction action="#{loginAction.redirectToHome}" immediate="true" />
</f:metadata>

Итак, я удалил if="#{identity.loggedIn}", чтобы вызвать мой redirectToHome метод, который перенаправляет на /pages/home.xhtml.

  • Если пользователь уже аутентифицирован, он перенаправляется на домашнюю страницу.
  • Если его нет, то он перенаправляется на домашнюю страницу, которая перенаправляет его на страницу входа в систему благодаря моему @ViewConfig

Вот это loginAction:

public void redirectToHome() throws IOException {
    externalContext.redirect(externalContext.encodeActionURL(externalContext.getRequestContextPath()+"/pages/home.xhtml"));
}

Проблема, с которой я столкнулся, была при выходе из системы.

Вот мое действие по выходу из системы:

<h:commandLink  action="/public/login" actionListener="#{securityAction.logout()}" value="Disconnect" immediate="true" />

И метод securityAction.logout():

public void logout() {
    identity.logout();
    if (!conversation.isTransient()) {
        conversation.end();
    }
}

Проблема в том, что меня перенаправили на страницу входа в систему (я думаю, благодаря @ViewConfig), , но PreLoginEvent не было брошено , поэтому шов LoginListener.observePreLoginEvent не был вызван, и поэтому мой предыдущий URL не был помещен в сессию. Поэтому, когда я вошел в систему (сразу после выхода из системы), я застрял на странице входа в систему, но вошел в систему.

Благодаря Брайану Литаму и он уже ответил , вот что я сделал: в моем authenticate методе моего BaseAuthenticator я вызвал этот метод после аутентификации:

private void overrideRedirectToLogin() {
    final String PRE_LOGIN_URL = LoginListener.class.getName() + "_PRE_LOGIN_URL";
    final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    final Map<String, Object> sessionMap = externalContext.getSessionMap();
    String redirectURL = (String) sessionMap.get(PRE_LOGIN_URL);

    if (redirectURL == null) {
        final HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        redirectURL = request.getRequestURL().toString();
    }

    sessionMap.put(PRE_LOGIN_URL, redirectURL.replace("/public/login.xhtml", "/pages/home.xhtml"));
}

При таком решении мой предыдущий URL не был установлен в сеансе, но, по крайней мере, мой пользователь перенаправлен на домашнюю страницу.

...