我有一个启用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>
答案 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)
以下是我将RememberMeServices
与Spring 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进行正常登录。