该代码大约一周前按预期工作,并用于解释访问 token 。现在突然开始抛出异常:
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-解释> FacebookOAuth2Template-> postForAccessGrant()
。在下面的代码片段中,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 图形访问 token API 返回的响应是:
{{"access_token":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","token_type":"bearer","expires_in":5157689}=[null]}
response.get
行尝试从值字段中检索这些值,在本例中为 null
。因此,它将 accessToken
和 expiry
值设置为 null
。
最佳答案
我添加了下面的类作为项目的临时修复,该项目覆盖了库中的现有类,但这不是一个正确的解决方案。有什么办法可以解决这个问题吗?
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);
}
}
关于java - Spring 社交 facebook 无法解码从 facebook 访问 token URI 发送的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43106228/