我遇到了这个问题,并使用 Spring Security RembereMe 服务基础架构的自定义实现解决了这个问题。这是您需要做的。
定义
public class LinkRememberMeService implements RememberMeServices, LogoutHandler
{
/**
* It might appear that once this method is called and returns an authentication object, that authentication should be finished and the
* request should proceed. However, spring security does not work that way.
*
* Once this method returns a non null authentication object, spring security still wants to run it through its authentication provider
* which, is totally brain dead on the part of Spring this, is why there is also a
* LinkAuthenticationProvider
*
*/
@Override
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response)
{
String accessUrl = ServletUtils.getApplicationUrl(request, "/special/");
String requestUrl = request.getRequestURL().toString();
if (requestUrl.startsWith(accessUrl))
{
// take appart the url extract the token, find the user details object
// and return it.
LinkAuthentication linkAuthentication = new LinkAuthentication(userDetailsInstance);
return linkAuthentication;
} else
{
return null;
}
}
@Override
public void loginFail(HttpServletRequest request, HttpServletResponse response)
{
}
@Override
public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication)
{
}
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
{
}
}
public class LinkAuthenticationProvider implements AuthenticationProvider
{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
// Spring Security is totally brain dead and over engineered
return authentication;
}
@Override
public boolean supports(Class<?> authentication)
{
return LinkAuthentication.class.isAssignableFrom(authentication);
}
}
整理其余的 spring security xml 以定义自定义身份验证提供程序和自定义记住我服务。
附:如果您在 URL 中对 GUID 进行 base64 编码,它将缩短几个字符。您可以使用 Apache commons codec base64 二进制编码器/解码器来做更安全的 url 链接。
public static String toBase64Url(UUID uuid)
{
return Base64.encodeBase64URLSafeString(toBytes(uuid));
}