【问题标题】:Spring social facebook unable to decode the information being sent from facebook access token URISpring social facebook 无法解码从 facebook 访问令牌 URI 发送的信息
【发布时间】:2017-08-23 16:36:11
【问题描述】:

代码在一周前按预期工作,用于解释访问令牌。现在突然开始抛出异常:

org.springframework.social.MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization.
    at org.springframework.social.facebook.api.impl.AbstractFacebookOperations.requireAuthorization(AbstractFacebookOperations.java:30)
    at org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:48)
    at org.springframework.social.facebook.connect.FacebookAdapter.setConnectionValues(FacebookAdapter.java:42)
    at org.springframework.social.facebook.connect.FacebookAdapter.setConnectionValues(FacebookAdapter.java:30)
    at org.springframework.social.connect.support.AbstractConnection.setValues(AbstractConnection.java:174)
    at org.springframework.social.connect.support.AbstractConnection.initKey(AbstractConnection.java:137)
    at org.springframework.social.connect.support.OAuth2Connection.<init>(OAuth2Connection.java:75)
    at org.springframework.social.connect.support.OAuth2ConnectionFactory.createConnection(OAuth2ConnectionFactory.java:91)
    at org.springframework.social.security.provider.OAuth2AuthenticationService.getAuthToken(OAuth2AuthenticationService.java:99)
    at org.springframework.social.security.SocialAuthenticationFilter.attemptAuthService(SocialAuthenticationFilter.java:239)
    at org.springframework.social.security.SocialAuthenticationFilter.attemptAuthentication(SocialAuthenticationFilter.java:157)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:85)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

我尝试调试库中的代码,发现返回的响应不是需要由spring-social-facebook-1.1.1.RELEASE-sources.jar-&gt; FacebookOAuth2Template-&gt; postForAccessGrant() 解释的所需格式。在下面的代码 sn-p 中,access_token 和 expires 需要使用键值。

@Override
    @SuppressWarnings("unchecked")  
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        MultiValueMap<String, String> response = getRestTemplate().postForObject(accessTokenUrl, parameters, MultiValueMap.class);
        String expires = response.getFirst("expires");
        return new AccessGrant(response.getFirst("access_token"), null, null, expires != null ? Long.valueOf(expires) : null);
    }

facebook graph access token API 返回的响应是:

{{"access_token":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","token_type":"bearer","expires_in":5157689}=[null]}

response.get 行试图从值字段中检索这些值,在本例中为 null。因此它将accessTokenexpiry 值设置为null

【问题讨论】:

标签: java spring facebook facebook-graph-api oauth-2.0


【解决方案1】:

我添加了下面的类作为项目的临时修复,它覆盖了库中的现有类,但这不是一个合适的解决方案。有什么办法可以解决这个问题吗?

package org.springframework.social.facebook.connect;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.social.support.ClientHttpRequestFactorySelector;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

public class FacebookOAuth2Template extends OAuth2Template {

    private static final Logger LOGGER = LogManager.getLogger(FacebookOAuth2Template.class);

    public FacebookOAuth2Template(String clientId, String clientSecret) {
        super(clientId, clientSecret, "https://www.facebook.com/v1.0/dialog/oauth", "https://graph.facebook.com/v1.0/oauth/access_token");
        setUseParametersForClientAuthentication(true);
    }

    @Override
    protected RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate(ClientHttpRequestFactorySelector.getRequestFactory());
        FormHttpMessageConverter messageConverter = new FormHttpMessageConverter() {
            @Override
            public boolean canRead(Class<?> clazz, MediaType mediaType) {
                // always read as x-www-url-formencoded even though Facebook sets contentType to text/plain
                return true;
            }
        };
        restTemplate.setMessageConverters(Collections.<HttpMessageConverter<?>> singletonList(messageConverter));
        return restTemplate;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        MultiValueMap<String, String> response = getRestTemplate().postForObject(accessTokenUrl, parameters, MultiValueMap.class);
        String expires = response.getFirst("expires");
        String accessToken = response.getFirst("access_token");
        if(!response.keySet().isEmpty() && (StringUtils.isEmpty(expires) || StringUtils.isEmpty(accessToken))) {
            for(String key : response.keySet()) {
                boolean valuesFound = false;
                HashMap<String, String> map;
                try {
                    //map = (HashMap<String, String>) JSONUtil.fromJSON(key, HashMap.class);
                    ObjectMapper objectMapper = new ObjectMapper();
                    map = objectMapper.readValue(key, HashMap.class);

                    if(StringUtils.isEmpty(expires)) {
                        expires = String.valueOf(map.get("expires_in"));
                        valuesFound = true;
                    }

                    if(StringUtils.isEmpty(accessToken)) {
                        accessToken = map.get("access_token");
                        valuesFound = true;
                    }

                    if(valuesFound) {
                        break;
                    }
                } catch(IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }
        return new AccessGrant(accessToken, null, null, expires != null ? Long.valueOf(expires) : null);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2018-10-27
    • 2012-10-23
    • 2016-11-10
    相关资源
    最近更新 更多