OAuth2.0 客户端实战

上一次课程,我们了解了 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.mzph.cn/news/52387.shtml

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

相关文章

「Java」《深度解析Java Stream流的优雅数据处理》

《深度解析Java Stream流的优雅数据处理》 一、引言1.1 背景1.2 Stream流的意义 二、Stream流的基本概念2.1 什么是Stream流2.2 Stream与传统集合的对比 三、创建Stream流3.1 通过集合创建Stream3.2 使用Arrays和Stream.of创建Stream3.3 从文件和网络流创建Stream 四、 中间操作…

Go 语言的实战案例 | 青训营

Powered by:NEFU AB-IN 文章目录 Go 语言的实战案例 | 青训营 Go补充简介猜数游戏在线词典项目 Go 语言的实战案例 | 青训营 GO语言工程实践课后作业&#xff1a;实现思路、代码以及路径记录 Go补充简介 在计算机编程领域&#xff0c;Go 语言&#xff08;也称为 Golang&…

[C++] STL_vector使用与常用接口的模拟实现

文章目录 1、vector的介绍2、vector的使用2.1 vector的定义2.2 vector迭代器的使用2.3 vector的空间增长问题 3、vector的增删查改3.1 push_back&#xff08;重点&#xff09;3.2 pop_back&#xff08;重点&#xff09;3.3 operator[]&#xff08;重点&#xff09;3.4 insert3.…

【SQL中DDL DML DQL DCL所包含的命令】

SQL中DDL DML DQL DCL所包含的命令 关于DDL、DML、DQL、DCL的定义和适用范围如下&#xff1a; 数据定义语言&#xff08;Data Definition Language&#xff0c;DDL&#xff09;&#xff1a; DDL用于创建、修改和删除数据库中的表、视图、索引等对象。它的主要命令包括CREATE、A…

ATA-7000系列高压放大器——应用场景介绍

ATA-7000系列是一款理想的可放大交、直流信号的高压放大器。单端输出20kVp-p&#xff08;10kVp&#xff09;高压&#xff0c;可以驱动高压型负载。电压增益数控可调&#xff0c;一键保存常用设置&#xff0c;为您提供了方便简洁的操作选择。 图&#xff1a;ATA-7000系列高压放大…

【分布式】VMware FT概要

讨论了1primary 1backup的情况&#xff0c;比较好理解&#xff0c; 6.824中以该论文为例&#xff0c;介绍了分布式系统中复制的概念&#xff0c;复制的方式。以下简要讲述一些关键点&#xff0c;来源于MIT6.824课程&#xff0c;翻译版本 https://mit-public-courses-cn-transl…

模板方法模式在JDBCTemplate中的应用

上一篇中系统总结了模板模式的原理和使用&#xff0c;提到了模板方法和回调接口。回调接口和模板方法类之间的关系可以看作服务与被服务的关系&#xff0c;模板方法类想要回调接口做事&#xff0c;就要提供相应的资源&#xff0c;接口用提供的资源做事&#xff0c;完事后&#…

【案例教程】基于R语言的物种气候生态位动态量化与分布特征模拟

在全球气候快速变化的背景下&#xff0c;理解并预测生物种群如何应对气候变化&#xff0c;特别是它们的地理分布如何变化&#xff0c;已经变得至关重要。利用R语言进行物种气候生态位动态量化与分布特征模拟&#xff0c;不仅可以量化描述物种对环境的需求和适应性&#xff0c;预…

Vue子组件向父组件传值(this.$emit()方法)

子组件使用this.$emit()向父组件传值 首先必须在父组件中引用子组件&#xff0c;然后实现传值 第一步 在父组件中引入子组件 使用import引入组件 import indexImportOrder from ./components/indexImportOrder 声明 //定义组件components:{indexImportOrder,}, 使用 &l…

shell 06(shell内置命令)

一、内置命令介绍 shell 内置命令&#xff0c;就是由 Bash shell 自身提供的命令&#xff0c;而不是文件系统中的可执行文件 使用type 来确定一个命令是否是内置命令: type 命令 通常来说&#xff0c;内置命令会比外部命令执行得更快: 执行外部命令时不但会触发磁盘 I/0&am…

Spring Boot使用MySQL的默认连接池

笔者在近期秋招面试的时候被问到了这个问题&#xff0c;现在简单梳理一下便于后期重新回顾&#xff0c;并加深记忆。 Spring Boot 默认使用的数据库连接池是 HikariCP(开源库地址)。 HikariCP 是目前性能最好的连接池之一&#xff0c;它具有高度的性能、可靠性和可扩展性&…

MyBatis的核心技术掌握,简单易懂(上)

目录 一.MyBatis中的动态SQL 二.MyBatis中的模糊查询 1. # 符号 2. $ 符号 ---问题 ---所以大家知道 # 和 $ 在MyBatis中的模糊查询中的区别了嘛&#xff1f;&#xff1f; 三.MyBatis 中的结果映射 1. resultType&#xff1a; 2. resultMap&#xff1a; ---问题 ---…

时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测(含KELM、ELM等对比)

时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测&#xff08;含KELM、ELM等对比&#xff09; 目录 时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测&#xff08;含KELM、ELM等对比&#xff09;预测效果基本介绍模型介绍程序设计参…

React Diff算法

文章目录 React Diff算法一、它的作用是什么&#xff1f;二、React的Diff算法1.了解一下什么是调和&#xff1f;2.react的diff算法3.React Diff的三大策略4.tree diff&#xff1a;1、如果DOM节点出现了跨层级操作&#xff0c;Diff会怎么办? 5. component diff&#xff1a;6. e…

使用ELK(ES+Logstash+Filebeat+Kibana)收集nginx的日志

文章目录 Nginx日志格式修改配置logstash收集nginx日志引入Redis收集日志写入redis从redis中读取日志 引入FilebeatFilebeat简介Filebeat安装和配置 配置nginx转发ES和kibanaELK设置账号和密码 书接上回&#xff1a;《ELK中Logstash的基本配置和用法》 Nginx日志格式修改 默认…

Jenkins的流水线详解

来源&#xff1a;u.kubeinfo.cn/ozoxBB 什么是流水线 声明式流水线 Jenkinsfile 的使用 什么是流水线 jenkins 有 2 种流水线分为声明式流水线与脚本化流水线&#xff0c;脚本化流水线是 jenkins 旧版本使用的流水线脚本&#xff0c;新版本 Jenkins 推荐使用声明式流水线。…

ROS2 学习(五)接口,动作

接口 通信双方统一规定好接口。比如图像 img&#xff0c;控制运动的线速度和角速度…… 我们也不用了解具体实现&#xff0c;基本就是了解接口会去用就行。 $ ros2 interface list # 展示所有 interfaces $ ros2 interface show ... # 显示具体一个 interface $ ros2 package…

搭建CFimagehost私人图床,实现公网远程访问的详细指南

文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

Android OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect 和 Apache HTTPClient 第一版 底层使用HTTPURLConnect 第二版 Square构建 从Android4.4开始 基本使用: val okhttp OkHttpClient()val request Request.Builder().url("http://www.baidu.com").buil…

PMP证书的正确打开方式 get✓

在职场竞争日益激烈的今天&#xff0c;拥有一项专业认证成为了许多人提升自身竞争力的必备条件。而作为项目管理领域的顶级认证&#xff0c;PMP证书备受关注。不过&#xff0c;很多人对于PMP证书的费用颇有顾虑。那么&#xff0c;PMP证书有什么补贴政策呢&#xff1f;下面就为大…