spring boot oauth2 facebook

前言

最近网站要接入facebook以及google两种第三方登录。查阅了很多的资料,终于算是勉强将facebook登录接入到了我们自己的项目中,这里记录整个facebook接入的整个流程和遇到的,方便日后自己查阅!

本篇文章只讲facebbok登录【暂无源码,有空了写个demo补上】


开发环境

电脑: Windows 10
项目技术: Spring boot + oauth2 + security
JDK:1.8.0_131
开发工具: IntelliJ IDEA

C:\Users\Administrator>java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

ps: 这里我特意列出了JDK的详细版本号,后面会提到是为什么(一个巨坑)~

准备工作

  1. 注册一个facebook账号
  2. shaodowscoks代理

开始

  1. 首先了解oauth2 facebook的工作原理。这里你需要了解什么是授权码模式。

相关资料

java内部代理:java 程序,springboot走shaodowscoks代理

遇到的坑

1 项目里面facebook连接超时(访问不了facebook,从而无法获取token,以及用户信息)

测试facebook接口时,postman能调通,而项目里面,Http请求一直报错:
java.net.ConnectException: Failed to connect to graph.facebook.com/31.13.74.17:443
错误截图
这里我确认了shaodowscoks代理是可用的,浏览器可以打开https://www.google.com

结论:因为facebook是国外的网站,在国内访问是需要代理的。而项目里面通过http出去的请求,是不会走shaodowscoks的,需要在代码里面将请求代理到我们本地!!

解决办法
在spring boot的启动类中加入下面一段代码,即可

// 代理到本地,走shaodowscoks
String proxyHost = "127.0.0.1";
// 1080是shaodowscoks的默认端口
String proxyPort = "1080";

System.setProperty("http.proxyHost", proxyHost);
System.setProperty("http.proxyPort", proxyPort);

// 对https也开启代理
System.setProperty("https.proxyHost", proxyHost);
System.setProperty("https.proxyPort", proxyPort);

详见:java 程序,springboot走shaodowscoks代理

2 项目部署到阿里云服务器,access_token报错

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://graph.facebook.com/oauth/access_token": Could not generate secret; nested exception is javax.net.ssl.SSLHandshakeException: Could not generate secret
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:607)
 at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:565)
 at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:137)
 ... 62 more
Caused by: javax.net.ssl.SSLHandshakeException: Could not generate secret
 at sun.security.ssl.ECDHCrypt.getAgreedSecret(ECDHCrypt.java:103)
 at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1067)
 at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:348)
 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 sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
 at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
 at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
 at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:80)
 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)
 ... 64 more
 Caused by: java.security.InvalidKeyException: ECDH key agreement requires ECPublicKey for doPhase
 at org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement.engineDoPhase(Unknown Source)
 at javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:567)
 at sun.security.ssl.ECDHCrypt.getAgreedSecret(ECDHCrypt.java:100)
  ... 64 more

分析日志,定位问题。
oauth2(项目内部)请求https://graph.facebook.com/oauth/access_token,获取token失败。原因Caused by: javax.net.ssl.SSLHandshakeException: Could not generate secret,这里大概可以看出来,是通过https协议去请求facebook,facebook那方失败了,服务器上没有证书??java项目如何访问https地址??

后面公司运维大神解释: 现在很多大公司都要求用https协议,因为安全。facebook,google等。然后ssl?对称加密,非对称加密,公钥、私钥???哈哈哈,我反正有点蒙蔽。 大概意思就是,公钥、私钥是一对一的,私钥在facebook那方,而公钥集中在各大浏览器网站,服务器,jdk中。
在这里插入图片描述

按照我的理解,项目内部访问https://graph.facebook.com/oauth/access_token之前,会将参与用facebook的公钥进行加密,然后发起请求。 等请求到了facebook那方,再用私钥解密,如果公钥和私钥是一对的,便能访问此接口。facebook那方便认为此次请求是合法的。

那么~需要在配置文件配置ssl相关的配置? NO, JDK自身就包含了许多的大厂的公钥,

解决办法将测试环境的JDK换成了1.8.0_131,虽然之前测试环境的jdk也是1.8, 但是1.8也有很多小版本,用1.8.0_131就对了。 换了之后,就可以访问facebook了! 巨坑!!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值