Как Seam 3 обрабатывает функцию "перенаправить на захват" после входа в систему?

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

У меня есть страница входа, которая /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 мой сценарий использования № 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 учебный класс...

Точка № 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 } "С результатом" успех "." Это только если я теперь снова получить доступ к 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 был отключен: каждый раз, когда я входил в систему, меня перенаправляли в дом.

Наконец, для моей точки № 4, s:viewAction делает работу


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

2 ответа

Решение

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

<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 не был помещен в сессию. Поэтому, когда я вошел в систему (сразу после выхода из системы), я застрял на странице входа в систему, но вошел в систему.

Благодаря Brian Leathem и его предыдущему ответу, вот что я сделал: в моем 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 не был установлен в сеансе, но, по крайней мере, мой пользователь перенаправлен на домашнюю страницу.

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

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

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

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

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

Другие вопросы по тегам