什么可能导致原始'OAuth2'状态参数在org.springframework.social.connect.web.ConnectSupport中为null?

bal*_*teo 9 oauth-2.0 spring-social spring-social-facebook

我正在尝试在我的应用程序上使用Spring Social,并且在调试时注意到我的应用程序上原始的"OAuth2"状态参数始终为null.

请参阅org.springframework.social.connect.web.ConnectSupport下面的Spring Social源代码:

private void verifyStateParameter(NativeWebRequest request) {
    String state = request.getParameter("state");
    String originalState = extractCachedOAuth2State(request);//Always null...
    if (state == null || !state.equals(originalState)) {
        throw new IllegalStateException("The OAuth2 'state' parameter is missing or doesn't match.");
    }
}

private String extractCachedOAuth2State(WebRequest request) {
    String state = (String) sessionStrategy.getAttribute(request, OAUTH2_STATE_ATTRIBUTE);
    sessionStrategy.removeAttribute(request, OAUTH2_STATE_ATTRIBUTE);
    return state;       
}
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙吗?

编辑:我确实看到facebook传回的状态参数:

Request URL:https://www.facebook.com/v2.5/dialog/oauth?client_id=414113641982912&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fconnect%2Ffacebook&scope=public_profile&state=0b7a97b5-b8d1-4f97-9b60-e3242c9c7eb9
Request Method:GET
Status Code:302 
Remote Address:179.60.192.36:443
Run Code Online (Sandbox Code Playgroud)

编辑2:顺便说一下,我得到的例外情况如下:

Exception while handling OAuth2 callback (The OAuth2 'state' parameter is missing or doesn't match.). Redirecting to facebook connection status page.
Run Code Online (Sandbox Code Playgroud)

bal*_*teo 3

事实证明,该问题是由于我依赖标头(而不是 cookie)来管理会话而引起的。

通过注释掉以下 spring 会话配置 bean:

@Bean
public HttpSessionStrategy sessionStrategy(){
    return new HeaderHttpSessionStrategy();
}
Run Code Online (Sandbox Code Playgroud)

oauth2 状态参数问题已解决。

PS 现在我必须找到一种方法让 Spring Social 与我当前的 Spring Session 配置一起工作......

编辑:我设法保留 HeaderHttpSessionStrategy (在 Spring 会话端)并通过实现我自己的 SessionStrategy (在 Spring 社交端)来使其工作,如下所示:

public class CustomSessionStrategy implements SessionStrategy {

    public void setAttribute(RequestAttributes request, String name, Object value) {
        request.setAttribute(name, value, RequestAttributes.SCOPE_SESSION);
    }

    public Object getAttribute(RequestAttributes request, String name) {
        ServletWebRequest servletWebRequest = (ServletWebRequest) request;
        return servletWebRequest.getParameter(name);
    }

    public void removeAttribute(RequestAttributes request, String name) {
        request.removeAttribute(name, RequestAttributes.SCOPE_SESSION);
    }
}
Run Code Online (Sandbox Code Playgroud)