Python入门篇.第88天—OAuth2.0 客户端实战

发布于 2023-12-30 | 作者: 纯洁的微笑 | 来源: 博客园 | 转载于: 博客园

上一次课程,我们了解了 OAuth 认证是怎么回事,以及了解了四种认证方式,今天我们将以 Github 为例,了解一下如何用 Flask 第三方应用

在之前的介绍 JWT 的时候,了解过 Authlib 库,Authlib 是集 JWT、OAuth1.0、OAuth2.0 于一身的终极 Python 认证框架,支持多种 Web 框架,例如 Django、requests、httpx,以及今天实践用的 Flask,还对 Django 和 Flask 做了专门的集成,让开发更简单

Github OAuth 应用时支持 OAuth2.0 协议的,用授权码的模式颁发 access_token,即 授权码模式(authorization code)

1、注册 github 第三方应用

首先需要去 github 上注册我们的应用,注册地址: https://github.com/settings/applications/new

从申请配置上可以看到,github 支持任意的域名,不需要做额外的认证和证明,这也是选择 github 做演示的原因,如果要用 微信 作为认证,需要申请开通开发者资质,比较麻烦,不过开发方式和都是类似的

申请成功后,可以看到自己创建的应用配置页面:

从上图红色框的位置,可以得到 client id, 和 client secret必须妥善保管

2、创建第三方应用

注册成功第三方应用,就可以来开发客户端了

1.1 安装 Authlib

使用 pip 安装

pip install Authlib

如果一切正常,可以导入 Authlib 模板,例如,引入 jwt :

>>> from authlib.integrations.flask_client import OAuth
>>>

1.2 创建 Web 应用

创建一个 Flask 应用:

from flask import Flask, session, render_template, url_for, redirect
from authlib.integrations.flask_client import OAuth

app = Flask(__name__)
app.secret_key = '!secret'

oauth = OAuth(app)

1.3 认证服务器配置

客户端需要做的是引导用户到认证页面,并且能能向认证服务器请求 access_token, OAuth 实例可以从应用的配置中读取

为了简便,将配置一同写入代码中,实际项目中建议使用单独的配置文件(后面 Flask 项目工程中会详细说明):

app.config["GITHUB_CLIENT_ID"] = '55ffa..<省略>...9e1fb3a'
app.config["GITHUB_CLIENT_SECRET"] = '692317a38d0..<省略>...d63f2d9f8c'
app.config["GITHUB_AUTHORIZE_URL"] = 'https://github.com/login/oauth/authorize'
app.config["GITHUB_AUTHORIZE_PARAMS"] = {
    'scope': 'user repo'
}
app.config["GITHUB_ACCESS_TOKEN_URL"] = 'https://github.com/login/oauth/access_token'
app.config["GITHUB_API_BASE_URL"] = 'https://api.github.com'

完成配置后,创建认证服务器实例:

github = oauth.register('github')

1.4 设置接入点(endpoint)

1.4.1 登录
@app.route('/login')
def login():
    redirect_uri = url_for('auth', _external=True)
    return github.authorize_redirect(redirect_uri)
1.4.2 认证回跳
@app.route('/auth/redirect')
def auth():
    token = github.authorize_access_token()
    user = github.get('user').json()
    """
     可以在此保存 token 和 用户信息,例如存入数据库
    """
    session['user'] = user
    return redirect('/')

实际应用中,可以在第一次获取用户信息后,引导用户用手机号或者邮箱注册,以便之后登录

1.4.3 首页
@app.route('/')
def homepage():
    user = session.get('user')
    return render_template('home.html', user=user)
1.4.4 登出
@app.route('/logout')
def logout():
    session.pop('user', None)
    return redirect('/')

1.5 刷新 access_token

github OAuth app 的 access_token 是长期的,不需要更新,这里用 Authlib 文档中的例子作为演示

OAuth2.0 协议中的 access_token 可以设置有效期,过期后需要用 refresh_token 重新获取

Authlib 提供了基于信号(类似于事件) 自动更新 access_token 的方法,会在合适的时间点,触发信号,执行更新函数

信号机制由 blinker 库,blinker 是一个简洁的,为 Python 对象之间提供广播式的信号机制的库,必须先安装:

pip install blinker

就不展开 blinker 了,只要知道它是自动更新 access_token 需要依赖的库就行

from authlib.integrations.flask_client import token_update

@token_update.connect_via(app)
def on_token_update(sender, name, token, refresh_token=None, access_token=None):
    if refresh_token:
        item = OAuth2Token.find(name=name, refresh_token=refresh_token)
    elif access_token:
        item = OAuth2Token.find(name=name, access_token=access_token)
    else:
        return

    # 更新 access_token
    item.access_token = token['access_token']
    item.refresh_token = token.get('refresh_token')
    item.expires_at = token['expires_at']
    item.save()

1.6 小试牛刀

启动 Flask 应用

python3 app.py

访问 http://localhost:5000,如果一切正常,将看到页面上有个 login 连接,点击此连接,将跳转到认证页面,登录 Github(如果当前浏览器中没登录 Github 的话),将看到授权页面,类似于:

http://127.0.0.1:5000 也能访问,但是必须使用 http://localhost:5000 来访问,即保持和注册时的首页 URL 一致

3、总结

本节课程演示了 Flask 基于 Authlib 完成简单认证客户端的示例,是对前面 OAuth 理论的一次实践,主要需要了解客户端的结构和认证流程:

总体来说,认证客户端的实现不复杂,主要是概念比较绕,建议下载示例代码,实践一下,加深理解

4、参考

示例代码:Python-100-days-day105