3

利用本地HTTPS模拟环境为FastAPI框架集成FaceBook社交三方登录

 2 years ago
source link: https://v3u.cn/a_id_174
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

利用本地HTTPS模拟环境为FastAPI框架集成FaceBook社交三方登录

首页 - Python /2020-09-06
利用本地HTTPS模拟环境为FastAPI框架集成FaceBook社交三方登录

    提起社交,就不得不说马克·扎克伯格(Mark Zuckerberg)一手创办的社交网络(FaceBook)。进入2020年,FaceBook的全球用户数已经突破了30亿,这是什么概念?全球人口大约70亿,除开中国14亿,还有56亿。国外市场是四倍于中国的潜在市场,扣除短期内有上网限制的人群,那也是两倍以上。站在全球视角看问题,说微信、支付宝偏安一隅,其实也并不为过。所以为你的平台集成全球最大用户基数的社交登录系统,显然可以为你带来更多的潜在用户,本次我们使用当红炸子鸡FastAPI框架来集成FaceBook的三方登录。

    首先在https://developers.facebook.com/上面注册开发者账号,并且创建一个应用:

20200906200916_80881.png

    输入一个应用名称

20200906200944_52437.png

    创建成功之后,需要加应用id(appid)和应用秘钥记录下来,之后会用到:

20200906200907_11718.png

    这之后添加产品,选择FaceBook登录,并且进行设置,将回调网址配置好,这是登录成功后跳转回网址的地址:

20200906200928_14062.png

    这里需要注意的是,FaceBook官方对安全性要求很高,它要求三方的应用强制使用HTTPS协议,而一般情况下本地环境的解决方案就是使用自签证书,所以这里使用一种更加简单友好的方式生成本地https证书,并且信任自签CA的方案——mkcert。

    mkcert是一个使用go语言编写的生成本地自签证书的小程序,具有跨平台,使用简单,支持多域名,自动信任CA等一系列方便的特性可供本地开发时快速创建https环境使用。

    安装方式也非常简单,由于Go lang的静态编译和跨平台的特性,官方提供各平台预编译的版本,直接下载到本地,给可执行权限(Linux/Unix需要)就可以了。Github地址:https://github.com/FiloSottile/mkcert
    如果是Win10平台,可以使用Chocolatey来安装:

choco install mkcert

    Mac os平台则可以使用Homebrew,非常方便:

brew install mkcert

    安装成功之后,运行命令将CA证书加入本地可信CA:

mkcert -install

    在Win10的可信CA列表可以找到该证书:

20200906200954_79553.png

    同理在Mac OS的证书列表同样也可以找到:

20200906200933_70239.png

    接下来我们就可以生成自签证书了,比如本地通过localhost或者127.0.0.1来访问你的web应用:

mkcert localhost 127.0.0.1 ::1

    会自动生成:

liuyue:blog liuyue$ mkcert localhost 127.0.0.1 ::1
Created a new local CA at "/Users/liuyue/Library/Application Support/mkcert" ????
Warning: the local CA is not installed in the system trust store! ⚠️
Warning: the local CA is not installed in the Firefox trust store! ⚠️
Warning: the local CA is not installed in the Java trust store! ⚠️
Run "mkcert -install" to avoid verification errors ‼️

Created a new certificate valid for the following names ????
- "localhost"
- "127.0.0.1"
- "::1"

The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem" ✅

    可以看到成功生成了localhost+2.pem证书文件和localhost+2-key.pem私钥文件。

    编写main.py用来运行FastAPI服务:

from user import router
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from model import database

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")

templates = Jinja2Templates(directory="templates")

app.include_router(router)


@app.on_event("startup")
async def startup():
await database.connect()


@app.on_event("shutdown")
async def shutdown():
await database.disconnect()

@app.get("/")
def read_root():
return {"Hello": "World"}

    现在将证书和私钥文件拷贝到你的FastAPI项目目录中,启动项目,这里启动时需要指定证书:

uvicorn main:app --ssl-keyfile localhost+2-key.pem --ssl-certfile localhost+2.pem

    访问 https://localhost:8000/,注意这里的协议要写为https

20200906200925_33669.png

    可以看到chrome浏览器已经认为这个网络服务是安全的了。

    由于我们现在已经安全部署了本地服务,就可以继续操作FaceBook了,编写login.html作为登录页面:

<html>
<head>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/zh_CN/sdk.js#xfbml=1&version=v8.0&appId=337974204227205&autoLogAppEvents=1" nonce="BBgy4tba"></script>
<script>
function login() {
FB.login(function(response){
console.log(response);
});
}
</script>

</head>
<body>
<h1>Facebook社交登录</h1>

<div class="fb-login-button" data-size="large" data-button-type="continue_with" data-layout="default" data-auto-logout-link="false"
data-onlogin="login" data-use-continue-as="false" data-width=""></div>


</body>
</html>

    登录页面中需要将代码里的appid改为你自己的自建应用的id。

    将login.html放入到FastAPI项目的static目录,随后访问它:https://localhost:8000/static/login.html

20200906200908_96654.png

    注意这里访问页面也必须采用https协议,之后点击按钮,用你的FaceBook账号登录:

20200906200907_23987.png

    如果登录成功,FaceBook会将回调的用户id以及accesstoken返回给当前页面,前端只要进行获取就可以了:

20200906200946_45108.png

    一般情况下,前端获取到秘钥之后,后端需要对其进行验证,用来防止有人进行篡改或者使用其他应用的appid来进行请求。

    这里我们编写一个后端的视图,用来验证用户token:

@router.get("/checklogin/")
async def check_login():

res = requests.get("https://graph.facebook.com/debug_token?access_token=337974204227205%7Cdc75d0a1fb30f2952db3a6a39e3f0ac0&input_token=EAAEzYsBi3oUBAHQQ9w7jSW95FcZBflMnib1cHUpf9eMBnuSvNcvvg31oKtIGoZA9kYtpq3OLMNSgY01ErgZA21PDRqdz7APrdZAXFJ9k43TnJXH8ZADb9Cjr2JEevZCdPpyTOpsZBvxE7RC63JjxZBr60iNQjWlfwwGBqdS2knhXBebpWGezrkg5WLRuBaUi3IdZBIBozQp1KMdDUmNWyR365")

res = json.loads(str(res.text))

return res

    这里需要注意的是User-token为用户登录的token(就是上面用户登录返回的accessToken),App-token是由appId和appSecret拼接而成,格式为 {appId}%7C{appSecret},%7C就是|urlencode之后的编码。

    访问FastAPI地址:https://localhost:8000/checklogin/

20200906200920_15470.png

    可以看到验证成功,我们可以将access_token存到后台即可,以后获取用户信息的时候就直接调用。

    紧接着我们就编写接口用token来换取用户信息:

@router.get("/getinfo/")
async def userinfo():

res = requests.get(
"https://graph.facebook.com/v8.0/1583917368454739?access_token=EAAEzYsBi3oUBAHQQ9w7jSW95FcZBflMnib1cHUpf9eMBnuSvNcvvg31oKtIGoZA9kYtpq3OLMNSgY01ErgZA21PDRqdz7APrdZAXFJ9k43TnJXH8ZADb9Cjr2JEevZCdPpyTOpsZBvxE7RC63JjxZBr60iNQjWlfwwGBqdS2knhXBebpWGezrkg5WLRuBaUi3IdZBIBozQp1KMdDUmNWyR365")

res = json.loads(str(res.text))

return res

    这里的含义就是获取用户id为1583917368454739的用户信息,访问:https://localhost:8000/getinfo/

20200906200902_53968.png

    用户信息轻松获取,更多的用户接口可以参照官方文档:https://developers.facebook.com/docs/graph-api/reference/user/

    结语:FaceBook三方登录的流程并不复杂,本篇主要是结合Go lang的mkcert库来生成自签证书以及FastAPI作为后端服务来实现本地模拟登录,这样就无须每次都在线上生产环境进行测试了。最后奉上FastAPI的项目地址:https://gitee.com/QiHanXiBei/fastapi_blog


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK