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

What could cause the original 'OAuth2' state parameter to be null in org.springframework.social.connect.web.ConnectSupport?

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

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

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

有人可以帮忙吗?

编辑:我确实看到状态参数被 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

edit 2:顺便说一下,我得到的异常如下:

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

您从 Facebook 获得的不是请求属性,而是请求参数。

您应该通过以下方式获取它:

request.getParameter("state")

原来这个问题是由于我 依赖 headers - 而不是 cookies - 来管理 session .

通过注释掉下面的springsession配置bean:

@Bean
public HttpSessionStrategy sessionStrategy(){
    return new HeaderHttpSessionStrategy();
}

oauth2 状态参数问题已解决。

P.S. 现在我必须找到一种方法让 Spring Social 与我当前的 [配置一起工作=37=] Session...

编辑:我设法保留了 HeaderHttpSession 策略(在 spring session 方面)并通过实施我自己的 Session 策略(在 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);
    }
}

试试这个解决方法,看看它是否适合你:

令我惊讶的是,我在 'incognito' 浏览器中打开了应用程序,一切正常。就这样。我认为在某些内容被缓存并导致问题之前。

我今天 运行 解决了这个问题,我的应用程序运行得非常好。我刚休息了几个小时,当我再次 运行 时,它开始抱怨“OAuth2 'state' 参数丢失或不匹配。” 状态参数首先放入会话中,然后请求发送到 facebook,请求返回相同的状态参数,但是当 spring 正在寻找会话对象以获取状态参数时,它没有找到会话.我认为它没有找到会话,因为当请求返回时它认为它是一个不同的客户端(或主机),即使旧的 HttpSession 对象仍然存在。容器为每个客户端维护一个 HttpSession。