我正在尝试使用Spring Security 5 OAuth2登录功能登录Google / Facebook。但我面临的问题是我正在编写无状态API,而Spring安全5使用HttpSessionOAuth2AuthorizationRequestRepository
来存储使用会话的授权请求。所以,我认为不要使用它并编写基于cookie的实现,如下所示:
public class HttpCookieOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
private static final String COOKIE_NAME = "some-name";
@Override
public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) {
Assert.notNull(request, "request cannot be null");
return fetchCookie(request)
.map(this::toOAuth2AuthorizationRequest)
.orElse(null);
}
@Override
public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request,
HttpServletResponse response) {
Assert.notNull(request, "request cannot be null");
Assert.notNull(response, "response cannot be null");
if (authorizationRequest == null) {
deleteCookie(request, response);
return;
}
Cookie cookie = new Cookie(COOKIE_NAME, fromAuthorizationRequest(authorizationRequest));
cookie.setPath("/");
cookie.setHttpOnly(true);
response.addCookie(cookie);
}
private String fromAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
return Base64.getUrlEncoder().encodeToString(
SerializationUtils.serialize(authorizationRequest));
}
private void deleteCookie(HttpServletRequest request, HttpServletResponse response) {
fetchCookie(request).ifPresent(cookie -> {
cookie.setValue("");
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
});
}
@Override
public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) {
// Question: How to remove the cookie, because we don't have access to response object here.
return loadAuthorizationRequest(request);
}
private Optional<Cookie> fetchCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0)
for (int i = 0; i < cookies.length; i++)
if (cookies[i].getName().equals(COOKIE_NAME))
return Optional.of(cookies[i]);
return Optional.empty();
}
private OAuth2AuthorizationRequest toOAuth2AuthorizationRequest(Cookie cookie) {
return SerializationUtils.deserialize(
Base64.getUrlDecoder().decode(cookie.getValue()));
}
}
以上基本上将数据存储在cookie而不是会话中。我有几个问题:
removeAuthorizationRequest
方法?我希望在那里删除cookie,但我们无法访问response
对象。更新:在https://github.com/spring-projects/spring-security/issues/5313创建了问题。在解决之前,我提出了一个解决方法:https://www.naturalprogrammer.com/blog/1681261/spring-security-5-oauth2-login-signup-stateless-restful-web-services