Вход в JSF через Facebook (SocialAuth) и поддержание сеанса работы

Я довольно долго зацикливался на этой проблеме и несколько раз переформулировал свой вопрос. Я буду откровенен с этим, предоставив реализацию ниже:


index.xhtml, краткая версия.

...
<f:event listener="#{userBacking.pullUserInfo}" type="preRenderView" />

<h:commandLink action="#{userBacking.login()}"  value="Login"  rendered="#{!userBacking.isLoggedIn()}"/>
<h:commandLink action="#{userBacking.logout()}" value="Logout" rendered="#{userBacking.isLoggedIn()}" />

<h:outputText rendered="#{userBacking.isLoggedIn()}" value="#{userBacking.userProfile.fullName}" />
...


UserBacking.java

/**
 * 
 * @author ggrec
 *
 */
@ManagedBean
@SessionScoped
public class UserBacking implements Serializable
{

    // ==================== 2. Instance Fields ============================

    private static final long serialVersionUID = -2262690225818595135L;

    /**
     * This is static for now. In the future, Google (and others) may be implemented.
     */
    public static final String SOCIAL_PROVIDER_ID = "facebook"; //$NON-NLS-1$


    // ==================== 2. Instance Fields ============================

    private SocialAuthManager socialAuthManager;

    private Profile userProfile;


    // ==================== 6. Action Methods =============================

    public void login() throws Exception
    {
        final Properties props = System.getProperties();
        props.put("graph.facebook.com.consumer_key", FACEBOOK_APP_ID); //$NON-NLS-1$
        props.put("graph.facebook.com.consumer_secret", FACEBOOK_APP_SECRET); //$NON-NLS-1$
        props.put("graph.facebook.com.custom_permissions", "email"); //$NON-NLS-1$ //$NON-NLS-2$
        final SocialAuthConfig config = SocialAuthConfig.getDefault();
        config.load(props);

        socialAuthManager = new SocialAuthManager();
        socialAuthManager.setSocialAuthConfig(config);

        final String authenticationURL = socialAuthManager.getAuthenticationUrl(SOCIAL_PROVIDER_ID, successURL());

        ContextHelper.redirect(authenticationURL);
    }


    public void logout() throws Exception
    {
        socialAuthManager.disconnectProvider(SOCIAL_PROVIDER_ID);

        ContextHelper.invalidateSession();
    }

    /*
     * Should fill up the profile, if a redirect from Facebook appers. Uhhh....
     */
    public void pullUserInfo() throws Exception
    {
        if (userProfile == null && socialAuthManager != null)
        {
            final HttpServletRequest req = (HttpServletRequest) ContextHelper.ectx().getRequest();
            final Map<String, String> reqParam = SocialAuthUtil.getRequestParametersMap(req);

            final AuthProvider authProvider = socialAuthManager.connect(reqParam);

            userProfile = authProvider.getUserProfile();

            ContextHelper.redirect( ContextHelper.getContextPath() );
        }
    }


    // ==================== 7. Getters & Setters ======================

    public Profile getUserProfile()
    {
        return userProfile;
    }


    public boolean isLoggedIn()
    {
        return userProfile != null;
    }


    // ==================== 9. Convenience Methods ========================

    private static String successURL()
    {
        return IApplicationConstants.APP_PSEUDO_URL + ContextHelper.getContextPath();
    }

}


Моя история

  • Прекрасно работает, если сеанс Facebook не существует в браузере. Если я уже вошел в систему, кажется, что socialAuthManager равно NULL, когда появляется code в параметрах запроса.

  • Я использую index.xhtml как для входа в систему, так и для обратного вызова.

  • f:event запускается pullUserInfo() каждый раз при рендеринге представления, надеясь, что при срабатывании метода в параметрах запроса будет указано code. Я понимаю, что все это неправильно.

  • Можно ли это сделать с помощью фильтра (например, когда Facebook перезвонит с code)?

  • Я не самый большой эксперт по JSF, поэтому мне может не хватать базовых знаний.


Ссылки


person GGrec    schedule 19.05.2014    source источник


Ответы (1)


Ответ довольно прост и в то же время глуп.

Сессия потеряна и создается как новая в каждом сервлете запрос

Я запускаю логин из http://devel-win8:1381/app/login, но обратный вызов находится в http://dev-machine:1381/app/callback (это другая реализация с сервлетами, но она также будет работать с кодом в вопросе).

Браузер создает разные сеансы для «голых» имен хостов.

Ваше здоровье.

person GGrec    schedule 20.05.2014