OAuth2.0 客户端实战

news2025/1/20 16:24:39

上一次课程,我们了解了 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)

注册 github 第三方应用

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

图片

github 应用申请注册

  • Homepage URL 应用的主地址,这里可以填写 Flask 本地的默认地址

  • Authorization callback URL: 认证完成后跳转的地址,可以根据项目具体情况填写

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

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

图片

github 应用注册成功

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

创建第三方应用

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

安装 Authlib

使用 pip 安装

pip install Authlib

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

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

创建 Web 应用

创建一个 Flask 应用:​​​​​​​

from flask import Flask, session, render_template, url_for, redirectfrom authlib.integrations.flask_client import OAuthapp = Flask(__name__)app.secret_key = '!secret'oauth = OAuth(app)
  • 引入可能用到的 Flask 框架模块和方法

  • 引入 Authlib 的 Flask 客户端模块

  • 创建 Flask 应用 app

  • 设置 应用的 secret_key, 用于做跳转认证页的校验,是必须的,如果缺失,引导认证页会失败

  • 用 Flask 应用实例化 OAuth

认证服务器配置

客户端需要做的是引导用户到认证页面,并且能能向认证服务器请求 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

  • _CLIENT_ID_CLIENT_SECRET:注册应用成功后,由认证服务器提供

  • _AUTHORIZE_URL:用户认证页面 URL,会在认证服务器文档中找到

  • _AUTHORIZE_PARAMS:认证时提供的额外参数,通常用于指定授权范围,具体范围和格式参考认证服务器文档

  • _ACCESS_TOKEN_URL:获取 access_token 的 URL

  • _API_BASE_URL:资源服务器 api 根路径,具体查看资源服务器 api 文档

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

github = oauth.register('github')
  • register 方法会根据配置创建认证服务器实例,参数同配置中的前缀,大小写随意

  • 返回认证服务器的实例,也可以用 oauth.github 方式来获取认证服务器实例

设置 接入点(endpoint)

登录​​​​​​​

@app.route('/login')def login():    redirect_uri = url_for('auth', _external=True)    return github.authorize_redirect(redirect_uri)
  • 用 url_for 函数得到 auth 视图函数的绝对访问路径,参数 _external 为 True 返回绝对路径

  • authorize_redirect 方法接收一个 URL 作为参数,即获得授权后的回调地址。注意:跳转地址必须和注册时的完全一致

  • authorize_redirect 方法会合成带参数的认证页 URL,并跳转过去

认证回跳​​​​​​​

@app.route('/auth/redirect')def auth():    token = github.authorize_access_token()    user = github.get('user').json()    """     可以在此保存 token 和 用户信息,例如存入数据库    """    session['user'] = user    return redirect('/')
  • 设置视图函数的接入点必须和注册时的回调保持一致,Flask 的接入点建议使用 / 结尾,能同时兼容不以 / 结尾请求,但是这里需要与注册时的保持一致,否则可能无法跳转到认证页

  • authorize_access_token 方法用于从认证服务器获取 access_token,分装了交互细节

  • get 方法用户获取用户的授权资源。参数为资源服务器 api 的名称,例如useruser/repos

  • 获得用户基本信息后,存入 session, 以便下次访问时获得

  • 最后跳转到首页上

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

首页​​​​​​​

@app.route('/')def homepage():    user = session.get('user')    return render_template('home.html', user=user)
  • 作为演示,首页很简单,即从 session 中获得 user 对象,将其内容显示在页面上,如果 user 为空,则显示登录连接

  • home.html 是模板,具体内容参考示例代码

登出​​​​​​​

@app.route('/logout')def logout():    session.pop('user', None)    return redirect('/')
  • 登出是客户端自身的功能,和认证服务器没关系,只要 access_token 有效,客户端就可以从资源服务器上获取用户的信息或资源

  • 登出仅将 user 从 session 中删掉,跳转到首页

刷新 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()
  • 先从 flask_client 包中引入 token_update 类

  • 定义更新 access_token 的回调函数 on_token_update, 通过注解 token_update.connect_via,注册成监听 access_token 更新事件的回调函数

  • 回调函数的参数

    • sender 是发出更新了 access_token 的实体,即认证服务器实例

    • name 就是注册认证服务器的名称,即 oauth.register 的第一个参数

    • token 为获得的新 access_token 对象

    • refresh_token 和 access_token 之前通过认证时获得的,access_token 是旧的

  • 回调函数逻辑部分,通过 refresh_token 或 access_token 从查找之前的 token 记录,找到后,将新的 token信息更新到记录中,并且保存。

  • OAuth2Token 可以理解成库表对象,用来和库表交互,维护 token 对象

小试牛刀

启动 Flask 应用

python3 app.py

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

图片

授权页面

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

总结

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

  • 在认证服务器上注册客户端,得到 client_id 和 client_secret

  • 设置登录、认证后回调的接入点(或叫做路由)

  • 管理获得的认证信息,用认证信息获取用户授权的资源

  • 设置刷新 access_token 的逻辑

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/925576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 eBPF 在云中实现网络可观测性

可观测性是一种了解和解释应用当前状态的能力&#xff0c;也是一种知道何时出现问题的方法。随着在 Kubernetes 和 OpenShift 上以微服务形式进行云部署的应用程序越来越多&#xff0c;可观察性受到了广泛关注。许多应用程序都有严格的承诺&#xff0c;比如在停机时间、延迟和吞…

战略企业家派:企业家愿景形成的过程

战略企业家派&#xff1a;战略的是企业家愿景形成的过程【安志强趣讲267期】 趣讲大白话&#xff1a;企业家才是关键因素 **************************** 战略企业家派的代表是熊彼特 他认为企业家的职责在创新 只有创新才能赢得更多利润 创新是新产品或新生产方式的各种组合 提…

学习心得04:CUDA

2018年的时候&#xff0c;看过同事使用CUDA。因为工作忙&#xff0c;所以也没请教。 近来买了本入门的CUDA书&#xff0c;学习了一番。有两个心得&#xff1a; 工作拆分。 CUDA是并行计算&#xff0c;也就是大量重复的可拆分的计算。数组最符合这个要求。简单点就是把数组外面…

接口多态 面试题及习题

基础题目 第一题&#xff1a;概念辨析 什么是接口&#xff0c;如何定义接口&#xff1f; 接口&#xff0c;是Java语言中一种引用类型&#xff0c;是方法的集合。使用interface关键定义接口&#xff0c;其中可以定义抽象方法&#xff0c;默认方法&#xff0c;私有方法&#xf…

实例044 在关闭窗口前加入确认对话框

实例说明 用户对程序进行操作时&#xff0c;难免会有错误操作的情况&#xff0c;例如不小心关闭程序&#xff0c;如果尚有许多资料没有保存&#xff0c;那么损失将非常严重&#xff0c;所以最好使程序具有灵活的交互性。人机交互过程一般都是通过对话框来实现的&#xff0c;对话…

基于SpringBoot母婴商城系统【附开题|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、商品信息推荐、商品资讯展示、查看更多等 ②商品信息、商品名称、标签、品牌等 ③添加购物车、立即购买、点我收藏、评论等 ④个人中心、我的订单、我的地址、我的收藏、支付等 后台登录&#xff1a; ①首页、个人中心&#xff1a;修改…

ElasticSearch-集成ik分词器

本文已收录于专栏 《中间件合集》 目录 背景介绍版本选择优势说明集成过程1.下载安装包2.解压安装包3.重启ElasticSearch服务3.1通过ps -ef | grep elastic查看正在启动的es进程号3.2使用kill -9 xxx 杀死进程3.3使用 ./elasticsearch 启动es服务 分词测试细粒度分词方式分词请…

git操作:将一个仓库的分支提交到另外一个仓库分支

这个操作&#xff0c;一般是同步不同网站的同个仓库&#xff0c;比如说gitee 和github。某个网站更新了&#xff0c;你想同步他的分支过来。然后基于分支开发或者其它。 操作步骤 1.本地先clone 你自己的仓库。也就是要push 分支的仓库。比如A仓库&#xff0c;把B仓库分支&am…

字节8年经验之谈 —— 如何设计一个自动化测试平台?

之前写过很多自动化测试相关的文章&#xff0c;后台有同学留言&#xff1a;希望写一篇自动化测试平台的文章。他的原话是这样&#xff1a;目前市场上开源或者商业的自动化测试平台很多&#xff0c;但试用下来总感觉有些地方不太融洽&#xff0c;想自己落地一个适合自己团队和项…

LC-1448. 统计二叉树中好节点的数目(DFS、)

1448. 统计二叉树中好节点的数目 中等 给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,…

Python案例|Matplotlib库实现的数据分析

数据展示是数据分析和挖掘中的重要环节&#xff0c;通过图形的形式可以直观、清晰地呈现数据内在的规律。 本文所用数据采用上一篇案例实现后的数据表&#xff0c;数据存储在newbj_lianJia.csv文件中&#xff0c;具体代码如下。 import pandas as pd #导入库 import matplot…

论文阅读_图形图像_U-NET

name_en: U-Net: Convolutional Networks for Biomedical Image Segmentation name_ch: U-Net&#xff1a;用于生物医学图像分割的卷积网络 addr: http://link.springer.com/10.1007/978-3-319-24574-4_28 doi: 10.1007/978-3-319-24574-4_28 date_read: 2023-02-08 date_publi…

基于“R语言+遥感“水环境综合评价方法教程

详情点击链接&#xff1a;基于"R语言遥感"水环境综合评价方法教程 一&#xff1a;R语言 1.1 R语言特点&#xff08;R语言&#xff09; 1.2 安装R&#xff08;R语言&#xff09; 1.3 安装RStudio&#xff08;R语言&#xff09; &#xff08;1&#xff09;下载地址…

MyBatis分页插件PageHelper的使用及特殊字符的处理

目录 一、PageHelper简介 1.什么是分页 2.PageHelper是什么 3.使用PageHelper的优点 二、PageHelper插件的使用 原生limit查询 1. 导入pom依赖 2. Mybatis.cfg.xml 配置拦截器 3. 使用PageHelper进行分页 三、特殊字符的处理 1.SQL注入&#xff1a; 2.XML转义&#…

C语言:选择+编程(每日一练Day8)

目录 选择题&#xff1a; 题一&#xff1a; 题二&#xff1a; 题三&#xff1a; 题四&#xff1a; 题五&#xff1a; 编程题&#xff1a; 题一&#xff1a;字符个数统计 思路一&#xff1a; 题二&#xff1a;多数元素 思路一&#xff1a; 本人实力有限可能对一些…

创建harbor仓库并进行一些操作

文章目录 前言一、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。二、安装搭建私有仓库 Harbor1、安装docker-compse2、安装harbor 3、修改配置文件4、运行脚本5 登入harbor仓库总结 前言 本篇文章需要完成的以下几个操作&#xff1a; 使用mysql:5.6和 ownclo…

0基础学习VR全景平台篇 第90篇:智慧眼-数据统计

【数据统计】是按不同条件去统计整个智慧眼项目中的热点&#xff0c;共包含四大块&#xff0c;分别是数据统计、分类热点、待审核、回收站&#xff0c;下面我们来逐一进行介绍。 1、数据统计 ① 可以按所属分类、场景分组、所属场景、热点类型以及输入热点名去筛选对应的热点&…

Spring之Spring生态系统的演进

未来展望&#xff1a;Spring生态系统的演进 未来展望&#xff1a;Spring生态系统的演进 摘要引言词汇解释详细介绍新技术趋势与影响开发方向与展望探讨Spring在未来的发展趋势微服务与云原生响应式编程强调开发效率和全栈式开发支持人工智能和大数据保持灵活性和创新性 针对新兴…

有效降低传导辐射干扰

一直以来&#xff0c;设计中的电磁干扰&#xff08;EMI&#xff09;问题十分令人头疼&#xff0c;尤其是在汽车领域。为了尽可能的减小电磁干扰&#xff0c;设计人员通常会在设计原理图和绘制布局时&#xff0c;通过降低高di / dt的环路面积以及开关转换速率来减小噪声源。 但…

SpringBootWeb案例 Part 4

3. 修改员工 需求&#xff1a;修改员工信息 在进行修改员工信息的时候&#xff0c;我们首先先要根据员工的ID查询员工的信息用于页面回显展示&#xff0c;然后用户修改员工数据之后&#xff0c;点击保存按钮&#xff0c;就可以将修改的数据提交到服务端&#xff0c;保存到数据…