Spring facebook登录:注册重定向

时间:2016-10-17 05:32:36

标签: spring spring-social spring-social-facebook

情景1 使用Facebook登录我的webapp

如果浏览器已登录Facebook,

如果用户的社交认证详细信息已在我的webapp中注册,

然后当用户点击"使用Facebook登录"在我的webapp上,

他/她获得Facebook和

返回的Authorization对象
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

是指定用户。

一切都很好。

情景2 如果浏览器未登录Facebook但

用户的社交认证详细信息已在我的webapp中注册,

然后当用户点击"使用Facebook登录"在我的webapp上,

用户通过输入用户名和密码BUT

登录Facebook

返回的Authorization对象
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

被授权为匿名并且名称为 anonymousUser

此外,授权后来自Facebook的电话是/ signup

但是,我期望与方案1中的注册用户相同

我的安全配置如下。任何人都可以给我一个关于问题可能是什么的提示吗?



<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/security
                    http://www.springframework.org/schema/security/spring-security.xsd">

	<security:http   use-expressions="true" entry-point-ref="appAuthenticationEntryPoint">

		<security:intercept-url pattern="/login"  access="permitAll()" />
		<security:intercept-url pattern="/flow-entry.html" access="permitAll()"/> 
		<security:intercept-url pattern="/flow-jobpostdata.html" access="permitAll()"/>
		<security:intercept-url pattern="/flow-jobpostdata_anydegree.html" access="permitAll()"/>
		  <security:intercept-url pattern="/j_spring_security_check" access="permitAll()"/>	
     <!-- Adds social authentication filter to the Spring Security filter chain. -->
        <security:custom-filter before="PRE_AUTH_FILTER" ref="socialAuthenticationFilter"/>
        <security:custom-filter position="FORM_LOGIN_FILTER" ref="SecurityAuthFilter"/>
	</security:http>

<!--  authentication manager and its provider( social provider deals with social login & local user provider deals with form login ) -->
    <security:authentication-manager alias="authenticationManager">
    
        <security:authentication-provider ref="socialAuthenticationProvider"/>
        <security:authentication-provider user-service-ref="localUserDetailService"/>
    </security:authentication-manager>
    

   

	<bean id="customAuthenticationProvider" class="com.ikoda.service.loginservices.CustomAuthenticationProvider">
			<property name="auService" ref="auService" />
	</bean> 

    <bean id="socialAuthenticationProvider" class="org.springframework.social.security.SocialAuthenticationProvider">
        <constructor-arg ref="inMemoryUsersConnectionRepository"/>
        <constructor-arg ref="socialUserDetailService"/>
    </bean>

    <!-- form login beans -->
  
    

     
     
     <bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    </bean>
     
     <bean id="appAuthenticationEntryPoint"
          class="com.ikoda.service.loginservices.AppAuthenticationEntryPoint">
        <constructor-arg name="loginFormUrl" value="/login"/>
    </bean>
    
    <bean id="rememberMeServices"
          class="org.springframework.security.web.authentication.NullRememberMeServices"/>

    <bean id="failureHandler"
          class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <constructor-arg name="defaultFailureUrl" value="/login?error=true"/>
    </bean>
    
    


    
    <bean class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
          id="SecurityAuthFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationSuccessHandler" ref="successHandler"/>
        <property name="authenticationFailureHandler" ref="failureHandler"/>
        <property name="filterProcessesUrl" value="/j_spring_security_check"/>
        <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>

    <!-- social login filter which is a pre authentication filter and works for /auth service url -->
    <bean id="socialAuthenticationFilter" class="org.springframework.social.security.SocialAuthenticationFilter">
        <constructor-arg name="authManager" ref="authenticationManager"/>
        <constructor-arg name="userIdSource" ref="userIdSource"/>
        <constructor-arg name="usersConnectionRepository" ref="inMemoryUsersConnectionRepository"/>
        <constructor-arg name="authServiceLocator" ref="appSocialAuthenticationServiceRegistry"/>
        <property name="authenticationSuccessHandler" ref="successHandler"/>
    </bean>


    <!-- inmemory connection repository which holds connection repository per local user -->
    <bean id="inMemoryUsersConnectionRepository"
          class="org.springframework.social.connect.mem.InMemoryUsersConnectionRepository">
        <constructor-arg name="connectionFactoryLocator" ref="appSocialAuthenticationServiceRegistry"/>
        <property name="connectionSignUp" ref="connectionSignUp"/>
    </bean>

    <!-- service registry will holds connection factory of each social provider-->
    <bean id="appSocialAuthenticationServiceRegistry"
          class="com.ikoda.service.loginservices.AppSocialAuthenticationServiceRegistry">
        <constructor-arg>
            <list>
                <ref bean="facebookAuthenticationService"/>
               <ref bean="googleAuthenticationService"/> 
            </list>
        </constructor-arg>
    </bean> 

    <bean id="facebookAuthenticationService"
          class="org.springframework.social.facebook.security.FacebookAuthenticationService">
        <constructor-arg name="apiKey" value="11111"/>
        <constructor-arg name="appSecret" value="11111"/>
    </bean>

    <bean id="googleAuthenticationService"
          class="org.springframework.social.google.security.GoogleAuthenticationService">
        <constructor-arg name="apiKey" value="111-lpmhcmuj1577bd6god0696g4u2g16c1i.apps.googleusercontent.com"/>
        <constructor-arg name="appSecret" value="111-111-"/>
    </bean>
    

    <bean id="userIdSource" class="org.springframework.social.security.AuthenticationNameUserIdSource"/>

    <!-- If no local user is associated to a social connection then connection sign up will create a new local user and map it to social user -->
    <bean id="connectionSignUp" class="com.ikoda.service.loginservices.AppConnectionSignUp"/>

</beans>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

重定向到signUp是Spring Social的预期行为。关键是如何管理行为。

解决问题的一种方法是通过在控制器注册方法中验证社交登录。要做到这一点,需要访问社交连接。您可以通过在控制器中自动装配ProviderSignInUtils来执行此操作。

注意AppConnectionSignUP是org.springframework.social.connect.ConnectionSignUp的一些实现

Connection<?> connection = providerSignInUtils.getConnectionFromSession(webRequest);
        if (null != connection)
        {

            String userIdString = appConnectionSignUp.execute(connection);
        }

解决问题的另一种方法是实现自己的ConnectionSignUp

&#13;
&#13;
    <bean id="connectionSignUp" class="com.ikoda.service.loginservices.AppConnectionSignUp"/>
&#13;
&#13;
&#13;

并在您的UsersConnectionRepository

中引用它

&#13;
&#13;
     <bean id="jdbcUsersConnectionRepository" 
              class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository">
            <constructor-arg ref="dataSource" />
            <constructor-arg ref="appSocialAuthenticationServiceRegistry" />
            <constructor-arg ref="textEncryptor" />
            <property name="connectionSignUp" ref="connectionSignUp"/>
        </bean>
&#13;
&#13;
&#13;

如果采用这种方法,那么社交登录将绕过Controller / signUp并直接调用connectionSignUP bean的execute方法。

同时,在上面的问题中,inMemoryUsersConnectionRepository是不明智的。我切换到jdbcUsersConnectionRepository。