2014-08-29 48 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的版本,因为它留下了让我能够正常登录的记住我的选择。