2014-08-29 41 views
3

我有一個啓用spring security的項目。我已經實現了使用可以正常工作的登錄表單記住我。但我也有登錄表單從谷歌/臉書社會登錄工作正常。問題是他們不記得用戶。有沒有辦法設置類似的「記住我」功能?實現一個記住我的春天社會

對於正常的登錄頁面我目前的Spring配置:

<http access-denied-page="/login?authorization_error=true" 
     disable-url-rewriting="true" authentication-manager-ref="formAuthenticationManager" 
     xmlns="http://www.springframework.org/schema/security"> 
     <intercept-url pattern="/account/**" access="ROLE_USER" /> 

     <remember-me key="iRemember" 
      token-validity-seconds="1209600" user-service-ref="formClientDetailsUserService" /> 
     <form-login authentication-failure-url="/login?authentication_error=true" 
      default-target-url="/account/" login-page="/login" 
      login-processing-url="/login.do" /> 
     <logout logout-success-url="http://example.com" logout-url="/logout" /> 
     <anonymous /> 
    </http> 

回答

1

我們切換到Java配置和創建的記得我的服務:

@Bean 
public MyRememberMeServices myRememberMeServices(){ 
     MyRememberMeServices service = new MyRememberMeServices (REMEMBERME_KEY, formUserDetailsService); 
     service.setAlwaysRemember(true); 
     service.setCookieName("xxxx"); 
     service.setParameter("_spring_security_remember_me"); 
     service.setTokenValiditySeconds(123); 
     return service; 
    }; 

,然後爲社會登錄的SignInAdapter實現:

@Override 
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) { 

    // load the user based on the account id 

    // create an authentication object to store in context 


    // set remember-me cookie 
    myRememberMeServices.onLoginSuccess(
     (HttpServletRequest) request.getNativeRequest(), 
     (HttpServletResponse) request.getNativeResponse(), 
     authentication); 

    // forward to the original URL 
    return extractOriginalUrl(request); 
} 
2

我有一些類似的要求。

我試圖讓身份驗證的網址爲/auth/facebook?_spring_security_remember_me=true(請參閱AbstractRememberMeServices.rememberMeRequested)。但是,org.springframework.social.security.SocialAuthenticationFilter.detectRejection不會讓這個傳遞。它是這樣編碼的:

protected boolean detectRejection(HttpServletRequest request) { 
    Set<?> parameterKeys = request.getParameterMap().keySet(); 
    return parameterKeys.size() > 0 
      && !parameterKeys.contains("oauth_token") 
      && !parameterKeys.contains("code") 
      && !parameterKeys.contains("scope"); 
} 

我想如果我們可以在那裏添加另一個子句,它可以工作。然後我想通過繼承SocialAuthenticationFilter來覆蓋它。但後來在SpringSocialConfigurer它沒有注入,但使用new關鍵字instanciated。子類SpringSocialConfigurer也似乎不是一個解決方案,因爲裏面有很多有用的私人領域。所以,我認爲一個解決方案就是將SpringSocialConfigurer複製到另一個班級中,並將其與SocialAuthenticationFilter的子類別一起使用。如果我已經正確理解了所有這些,所有這些似乎都是黑客行爲,我認爲我們應該創建一個票據,以便正確記住我的支持。

當然,如果我們要記住我是一直在,這是通過設置RememberMeServicesalwaysRemember場容易的,我這樣做是這樣的:

@Bean 
public RememberMeServices rememberMeServices() { 

    TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices(rememberMeKey, userService); 
    rememberMeServices.setAlwaysRemember(true); 
    return rememberMeServices; 

} 
+0

創建了一張票:https://jira.spring.io/browse/SOCIAL-448 – Sanjay 2015-01-22 11:01:11

+0

我有興趣總是記住我,並且我已經添加了setAlwaysRemember(true)。但是,春天似乎忽視了社交。那麼我如何將RememberMeServices與社交結合? – checklist 2015-10-27 09:55:36

+0

rememberMeServices.setAlwaysRemember(真),正如上文是爲我工作,我記得。 – Sanjay 2015-10-27 11:02:24

1

因此,這裏是我所做整合RememberMeServicesSpring social。就像@桑傑說的,它基於AlwaysRemember=true邏輯。

而是默認TokenBasedRememberMeServices,我們定製了一點:

public class DynamicRememberMeServices extends TokenBasedRememberMeServices { 

public final static String PARAM_BASED_KEY = "remember-me-param-based"; 
public final static String REMEMBER_ME_KEY = "remember-me"; 

private Logger logger = LoggerFactory.getLogger(getClass()); 

public DynamicRememberMeServices(String key, UserDetailsService userDetailsService){ 
    super(key, userDetailsService); 
    super.setParameter(REMEMBER_ME_KEY); 
    super.setCookieName(REMEMBER_ME_KEY); 
} 

@Override 
protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { 
    if("on".equalsIgnoreCase(request.getParameter(PARAM_BASED_KEY))){ 
     logger.debug("param based request"); 
     return super.rememberMeRequested(request, parameter); 
    } 
    logger.debug("always remember me"); 
    return true; 
} 

}

,並在login.html

<form th:action="@{/login}" method="post"> 
    User Name : <input type="text" name="username"/> 
    Password: <input type="password" name="password"/> 
    <input type="hidden" name="remember-me-param-based" value="on" /> 
    Remember me: <input type='checkbox' name='remember-me' checked="checked"/> 
    <input type="hidden" name="_csrf" th:value="${_csrf.token}"/> 
    <input type="submit" value="Sign In"/> 
</form> 

<a th:href="@{/auth/facebook}">Or via facebook</a> 

所以在Facebook登錄(通過/auth/facebook)的情況下,將採用AlwaysRememberMe策略,返回true,但對於傳統的form-login,這取決於:

  • 如果remember-me-param-based=on請求主體,它會檢查根據給定的參數(remember-me)作爲傳統TokenBasedRememberMeServices繼續。
  • 如果缺少remember-me-param-based,則其作爲AlwaysRememberMe

恕我直言,我的實施至少給了「傳統登錄」用戶的選擇。

+0

我想你的方式,但我仍然不能綁了rememberMe服務社會登錄。有沒有一個設置? – checklist 2015-10-27 09:56:24

+0

你正在使用的'''ProviderSignInController'''右'''SocialAuthenticationFilter'''呢?如果是這樣,你只需要像'''http.rememberMeServices(rememberMeServices())'''一樣定期注入它。 – beku8 2015-10-29 01:49:39

1

要回答這個問題,原來的方式,被問到(使用XML配置)時,Spring Security 3.2+支持remember-me元素上的services-ref屬性。因此,在您的安全配置你會:

<security:http xmlns="http://www.springframework.org/schema/security"> 
    ... 
    <remember-me services-ref="rememberMeServices" key="secret-key"> 
</security:http> 

<bean id="rememberMeServices" class="com.example.MyRememberMeServices"> 
    <constructor-arg index="0" value="secret-key" /> 
    <constructor-arg index="1" ref="userDetailsService" /> 
    <property name="tokenValiditySeconds" value="1000000" /> 
</bean> 

其中MyRememberMeServices可以清單的版本或beku8的DynamicRememberMeServices。我更喜歡beku8的版本,因爲它留下了讓我能夠正常登錄的記住我的選擇。