即使忽略 ssl 问题也出错:无法找到到请求目标的有效认证路径

即使忽略 ssl 问题也出错:无法找到到请求目标的有效认证路径

问题描述:

我遇到了一个奇怪的问题.在开发应用程序时,我使用 spring social 为用户提供 Facebook 帐户登录.我现在使用 ssl 脚本忽略证书检查,如下所示.问题是,当我尝试从 Facebook 访问令牌时,此脚本有效,但是当我尝试访问用户个人资料时,它会引发错误

I'm facing a strange issue. While developing an application, I'm using spring social to provide login with a Facebook account to a user. I'm ignoring certificate check for now using a script for ssl as shown below. The problem is that when I try to get access to the token from Facebook, this script works but when i try to access a user profile, it throws an error

sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

我还尝试为我的本地主机创建一个自签名证书并将其添加到我的 Java 密钥库中,但没有任何帮助.

I also tried to create a self signed certificate for my localhost and add it in my java keystore but nothing helps.

Facebook 控制器.java

Facebook Controller.java

@RequestMapping(value = "/social/facebook")
@Component
public class FacebookController<FacebookApi> {

    private static final Logger LOGGER = LoggerFactory
            .getLogger(FacebookController.class);

    private static final String PUBLISH_SUCCESS = "success";
    private static final String FACEBOOK = "facebook";


    @Autowired
    private ConnectionFactoryRegistry connectionFactoryRegistry;

    @Autowired
    private OAuth2Parameters oAuth2Parameters;


    @Autowired
    @Qualifier("facebookServiceProvider")
    private OAuthServiceProvider<FacebookApi> facebookServiceProvider;


    @RequestMapping(value = "/signin", method = RequestMethod.GET)
    public ModelAndView signin(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        System.out.println("Redirecting to Facebook.........");
        System.out.println(System.getProperty("java.home"));
        System.setProperty( "http.proxyPort", "80" );
        System.setProperty( "https.proxyPort", "80" );
        System.setProperty( "http.proxyHost", "10.68.248.98" );
        System.setProperty( "https.proxyHost", "10.68.248.98" );

        FacebookConnectionFactory facebookConnectionFactory = (FacebookConnectionFactory) connectionFactoryRegistry
                .getConnectionFactory(FACEBOOK);
        OAuth2Operations oauthOperations = facebookConnectionFactory
                .getOAuthOperations();
        oAuth2Parameters.setState("recivedfromfacebooktoken");
        String authorizeUrl = oauthOperations.buildAuthorizeUrl(
                GrantType.AUTHORIZATION_CODE, oAuth2Parameters);
        RedirectView redirectView = new RedirectView(authorizeUrl, true, true,
                true);
        System.out.println("Redirecting to Facebook again.........");
        return new ModelAndView(redirectView);
    }

    @RequestMapping(value = "/callback", method = RequestMethod.GET)
    @ResponseBody
    public void postOnWall(@RequestParam("code") String code,
            @RequestParam("state") String state, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        OAuthService oAuthService = facebookServiceProvider.getService();
        System.out.println(oAuthService.getVersion());
        Verifier verifier = new Verifier(code);
        getSSL();
        Token accessToken =oAuthService.getAccessToken(Token.empty(), verifier);
        //System.out.println(accessToken);
        //System.out.println(accessToken.getToken());
        //getSSL();
        FacebookTemplate template = new FacebookTemplate(accessToken.getToken());
        //System.out.println(template);

        **// ERROR COMES HERE**

        User facebookProfile = template.userOperations().getUserProfile();
        //System.out.println(facebookProfile);
        String userId = facebookProfile.getId();
        //System.out.println(facebookProfile.getEmail());
        //System.out.println(facebookProfile.getFirstName());

        LOGGER.info("Logged in User Id : {}", userId);
        response.sendRedirect("/j_spring_security_check?j_username="+userId);
        //return "success";
    }

    @RequestMapping(value = "/callback", params = "error_reason", method = RequestMethod.GET)
    @ResponseBody
    public void error(@RequestParam("error_reason") String errorReason,
            @RequestParam("error") String error,
            @RequestParam("error_description") String description,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            LOGGER.error(
                    "Error occurred while validating user, reason is : {}",
                    errorReason);
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, description);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void getSSL(){
        SSLContext sslContext=null;
        try {
            sslContext= SSLContext.getInstance("SSL");

            // set up a TrustManager that trusts everything
            sslContext.init(null, new TrustManager[] { new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs,
                        String authType) {
                    System.out.println("checkClientTrusted =============");
                }

                public void checkServerTrusted(X509Certificate[] certs,
                        String authType) {
                    System.out.println("checkServerTrusted =============");
                }
            } }, new SecureRandom());
        } catch (KeyManagementException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch(NoSuchAlgorithmException e){
            e.printStackTrace();
        }

        if(sslContext!=null){
            HttpsURLConnection.setDefaultSSLSocketFactory(
                    sslContext.getSocketFactory());

            HttpsURLConnection
            .setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String arg0, SSLSession arg1) {
                    System.out.println("hostnameVerifier =============");
                    return true;
                }
            });

        }
    }

}

错误:

Redirecting to Facebook.........

D:\Java\jdk1.8.0_92\jre

Redirecting to Facebook again.........

2.0

checkServerTrusted =============

getAcceptedIssuers =============

Jul 22, 2016 7:50:33 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring-dispatcher] in context with path [/CIPlatform] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://graph.facebook.com/v2.5/me?fields=id%2Cabout%2Cage_range%2Cbio%2Cbirthday%2Ccontext%2Ccover%2Ccurrency%2Cdevices%2Ceducation%2Cemail%2Cfavorite_athletes%2Cfavorite_teams%2Cfirst_name%2Cgender%2Chometown%2Cinspirational_people%2Cinstalled%2Cinstall_type%2Cis_verified%2Clanguages%2Clast_name%2Clink%2Clocale%2Clocation%2Cmeeting_for%2Cmiddle_name%2Cname%2Cname_format%2Cpolitical%2Cquotes%2Cpayment_pricepoints%2Crelationship_status%2Creligion%2Csecurity_settings%2Csignificant_other%2Csports%2Ctest_group%2Ctimezone%2Cthird_party_id%2Cupdated_time%2Cverified%2Cvideo_upload_limits%2Cviewer_can_send_gift%2Cwebsite%2Cwork": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
    at org.apache.http.impl.conn.HttpClientConnectionOperator.upgrade(HttpClientConnectionOperator.java:167)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.upgrade(PoolingHttpClientConnectionManager.java:329)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:398)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:91)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
    at org.springframework.social.oauth2.OAuth2RequestInterceptor.intercept(OAuth2RequestInterceptor.java:45)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85)
    at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.http.client.BufferingClientHttpRequestWrapper.executeInternal(BufferingClientHttpRequestWrapper.java:56)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
    at org.springframework.social.oauth2.OAuth2RequestInterceptor.intercept(OAuth2RequestInterceptor.java:45)
    at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85)
    at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:596)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:572)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:280)
    at org.springframework.social.facebook.api.impl.FacebookTemplate.fetchObject(FacebookTemplate.java:225)
    at org.springframework.social.facebook.api.impl.FacebookTemplate.fetchObject(FacebookTemplate.java:220)
    at org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:53)
    at org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:49)
    at com.tools.infosys.ciplatform.servlets.FacebookController.postOnWall(FacebookController.java:122)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    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:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

我终于让它在我身边工作了.

I finally get it working on my side.

1.我必须将 Facebook Graph SSL 证书导入我的服务器密钥库.

1. I had to import the Facebook Graph SSL certificate into my server keystore.

  • 转到 https://graph.facebook.com 并下载证书作为 base 64 文件.
  • 将证书导入您的密钥库.默认密钥库密码是 changeit.
  • Go to https://graph.facebook.com and download the certificate as a base 64 file.
  • Import the certificate to your keystore. Default keystore password is changeit.

Keytool 命令:

keytool -import -alias star.facebook.com -keystore <JRE_HOME>\lib\security\cacerts -file star.facebook.com

2. JVM 似乎使用了不受支持的 TLS 版本.由于我在 GNU/Linux 上安装了 openJDK,因此 JCE Unlimited Strength 已经存在.无需在这里做任何事情.

2. It appears that the JVM may be using an unsupported TLS version. Since I have the openJDK on GNU/Linux, the JCE Unlimited Strength is already present. No need to do something here.

  • 如果您没有它(例如 OracleJDK),您可以下载它此处.
  • 如果您愿意,可以改为设置 JVM 参数:

命令行

java -Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1 ...

系统参数

System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1");

3. Spring Social 2.0.3.RELEASE 由于不推荐使用的字段(bio")在尝试访问 Graph API v2.8 时将无法正常用于检索用户配置文件.

3. Spring Social 2.0.3.RELEASE will not work properly for the retrieving of user profiles if trying to access the Graph API v2.8 due to deprecated fields ("bio").

而不是...

User userProfile = facebook.userOperations().getUserProfile(); // Error

...使用这个:

String [] fields = { "id", "email", "first_name", "last_name" };

User userProfile = facebook.fetchObject("me", User.class, fields);

所有参考文献: