实现一个记住我的春天 - 社交

时间:2014-08-29 09:50:47

标签: java spring-security spring-social

我有一个启用Spring安全性的项目。我已经实现了一个记住我使用登录表单工作正常。但我也有登录表单来自google / facebook的社交登录,工作正常。问题是他们不记得用户。有没有办法设置类似的"记住我"功能?

我目前正常登录页面的弹簧配置:

<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>

4 个答案:

答案 0 :(得分: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关键字进行实例化。子类化SpringSocialConfigurer似乎也不是一个解决方案,因为里面有许多有用的私有字段。因此,我认为解决方案是将SpringSocialConfigurer复制到另一个类中,并将其与子类SocialAuthenticationFilter一起使用。如果我已经正确地理解了这一切,那么这一切似乎都是黑客行为,而且我认为我们应该创建一张能够让我记住支持的门票。

当然,如果我们想要记住我永远在线,那么通过设置alwaysRemember的{​​{1}}字段就可以轻松实现,而且我这样做:

RememberMeServices

答案 1 :(得分:1)

以下是我将RememberMeServicesSpring social进行整合的方法。就像@Sanjay所说,它基于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来自请求正文,则会根据给定参数(TokenBasedRememberMeServices)检查继续为传统remember-me
  • 如果缺少remember-me-param-based,则其工作为AlwaysRememberMe

恕我直言,我的实施至少可以选择&#34;传统登录&#34;用户。

答案 2 :(得分: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);
}

答案 3 :(得分:1)

要回答这个问题,问题的原始方式(使用XML配置),Spring Security 3.2+支持remember-me元素的services-ref属性。因此,在您的安全配置中,您将拥有:

parser.require(XmlPullParser.START_TAG,ns,"channel");
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }

其中MyRememberMeServices可以是核对表的版本或beku8的DynamicRememberMeServices。我更喜欢beku8的版本,因为它可以选择启用remember-me进行正常登录。