用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api

简介: [新添加] 本文对应的源码 (多个flow, clients, 调用python api): https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks 目前正在使用asp.

[新添加] 本文对应的源码 (多个flow, clients, 调用python api): https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks

目前正在使用asp.net core 2.0 (主要是web api)做一个项目, 其中一部分功能需要使用js客户端调用python的pandas, 所以需要建立一个python 的 rest api, 我暂时选用了hug, 官网在这: http://www.hug.rest/.

目前项目使用的是identity server 4, 还有一些web api和js client.

项目的早期后台源码: https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplate

下面开始配置identity server 4, 我使用的是windows.

添加ApiResource:

在 authorization server项目中的配置文件添加红色部分, 这部分就是python hug 的 api:

public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource(SalesApiSettings.ApiName, SalesApiSettings.ApiDisplayName) {
                    UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email }
                },
                new ApiResource("purchaseapi", "采购和原料库API") {
                    UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email }
                },
                new ApiResource("hugapi", "Hug API") {
                    UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email }
                }
            };
        }

修改js Client的配置:

// Sales JavaScript Client
                new Client
                {
                    ClientId = SalesApiSettings.ClientId,
                    ClientName = SalesApiSettings.ClientName,
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,
                    AccessTokenLifetime = 60 * 10,
                    AllowOfflineAccess = true,
                    RedirectUris =           { $"{Startup.Configuration["MLH:SalesApi:ClientBase"]}/login-callback", $"{Startup.Configuration["MLH:SalesApi:ClientBase"]}/silent-renew.html" },
                    PostLogoutRedirectUris = { Startup.Configuration["MLH:SalesApi:ClientBase"] },
                    AllowedCorsOrigins =     { Startup.Configuration["MLH:SalesApi:ClientBase"] },
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        SalesApiSettings.ApiName,
                        "hugapi"
                    }
                }

修改js客户端的oidc client配置选项:

添加 hugapi, 与authorization server配置对应.

{
        authority: 'http://localhost:5000',
        client_id: 'sales',
        redirect_uri: 'http://localhost:4200/login-callback',
        response_type: 'id_token token',
        scope: 'openid profile salesapi hugapi email',
        post_logout_redirect_uri: 'http://localhost:4200',

        silent_redirect_uri: 'http://localhost:4200/silent-renew.html',
        automaticSilentRenew: true,
        accessTokenExpiringNotificationTime: 4,
        // silentRequestTimeout:10000,
        userStore: new WebStorageStateStore({ store: window.localStorage })
    }

建立Python Hug api

(可选) 安装virtualenv:

pip install virtualenv

然后在某个地方建立一个目录:

mkdir hugapi && cd hugapi

建立虚拟环境:

virtualenv venv

激活虚拟环境:

venv\Scripts\activate

然后大约这样显示:

安装hug:

pip install hug

这时, 参考一下hug的文档. 然后建立一个简单的api. 建立文件main.py:

import hug

@hug.get('/home')
def root():
    return 'Welcome home!'

运行:

hug -f main.py

结果好用:

然后还需要安装这些:

pip install cryptography pyjwt hug_middleware_cors

其中pyjwt是一个可以encode和decode JWT的库, 如果使用RS256算法的话, 还需要安装cryptography. 

而hug_middleware_cors是hug的一个跨域访问中间件(因为js客户端和这个api不是在同一个域名下).

添加需要的引用:

import hug
import jwt
import json
import urllib.request
from jwt.algorithms import get_default_algorithms
from hug_middleware_cors import CORSMiddleware

然后正确的做法是通过Authorization Server的discovery endpoint来找到jwks_uri,

identity server 4 的discovery endpoint的地址是:

http://localhost:5000/.well-known/openid-configuration, 里面能找到各种节点和信息:

 

但我还是直接写死这个jwks_uri吧:

response = urllib.request.urlopen('http://localhost:5000/.well-known/openid-configuration/jwks')
still_json = json.dumps(json.loads(response.read())['keys'][0])

identity server 4的jwks_uri, 里面是public key, 它的结构是这样的:

而我使用jwt库, 的参数只能传入一个证书的json, 也可就是keys[0].

所以上面的最后一行代码显得有点.......

如果使用python-jose这个库会更简单一些, 但是在我windows电脑上总是安装失败, 所以还是凑合用pyjwt吧.

然后让hug api使用cors中间件:

api = hug.API(__name__)
api.http.add_middleware(CORSMiddleware(api))

然后是hug的authentication部分:

def token_verify(token):
    token = token.replace('Bearer ', '')
    rsa = get_default_algorithms()['RS256']
    cert = rsa.from_jwk(still_json)
    try:
        result = jwt.decode(token, cert, algorithms=['RS256'], audience='hugapi')
        print(result)
        return result
    except jwt.DecodeError:
        return False

token_key_authentication = hug.authentication.token(token_verify)

通过rsa.from_jwk(json) 就会得到key (certificate), 然后通过jwt.decode方法可以把token进行验证并decode, 算法是RS256, 这个方法要求如果token里面包含了aud, 那么方法就需要要指定audience, 也就是hugapi.

最后修改api 方法, 加上验证:

@hug.get('/home', requires=token_key_authentication)
def root():
    return 'Welcome home!'

最后运行 hug api:

hug -f main.py

端口应该是8000.

运行js客户端,登陆, 并调用这个hug api http://localhost:8000/home:

(我的js客户端是angular5的, 这个没法开源, 公司财产, 不过配置oidc-client还是很简单的, 使用)

返回200, 内容是: 

看一下hug的log:

token被正确验证并解析了. 所以可以进入root方法了.

 
其他的python api框架, 都是同样的道理.

[新添加] 本文对应的源码 (多个flow, clients, 调用python api): https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks

可以使用这个例子自行搭建 https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/7_JavaScriptClient 

官方还有一个nodejs api的例子: https://github.com/lyphtec/idsvr4-node-jwks

今日修改后的代码: 

import json
import hug
import jwt
import requests
from jwt.algorithms import get_default_algorithms
from hug_middleware_cors import CORSMiddleware

api = hug.API(__name__)
api.http.add_middleware(CORSMiddleware(api))


def token_verify(token):
    access_token = token.replace('Bearer ', '')
    token_header = jwt.get_unverified_header(access_token)
    res = requests.get(
        'http://localhost:5000/.well-known/openid-configuration')
    jwk_uri = res.json()['jwks_uri']
    res = requests.get(jwk_uri)
    jwk_keys = res.json()

    rsa = get_default_algorithms()['RS256']
    key = json.dumps(jwk_keys['keys'][0])
    public_key = rsa.from_jwk(key)

    try:
        result = jwt.decode(access_token, public_key, algorithms=[
                            token_header['alg']], audience='api1')
        return result
    except jwt.DecodeError:
        return False


token_key_authentication = hug.authentication.token(token_verify)


@hug.get('/identity', requires=token_key_authentication)
def root(user: hug.directives.user):
    print(user)
    return user

 我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan

下面是我的关于ASP.NET Core Web API相关技术的公众号--草根专栏:

目录
相关文章
|
10天前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
10天前
|
JSON 数据可视化 API
Python 中调用 DeepSeek-R1 API的方法介绍,图文教程
本教程详细介绍了如何使用 Python 调用 DeepSeek 的 R1 大模型 API,适合编程新手。首先登录 DeepSeek 控制台获取 API Key,安装 Python 和 requests 库后,编写基础调用代码并运行。文末包含常见问题解答和更简单的可视化调用方法,建议收藏备用。 原文链接:[如何使用 Python 调用 DeepSeek-R1 API?](https://apifox.com/apiskills/how-to-call-the-deepseek-r1-api-using-python/)
|
26天前
|
监控 算法 安全
深度洞察内网监控电脑:基于Python的流量分析算法
在当今数字化环境中,内网监控电脑作为“守城卫士”,通过流量分析算法确保内网安全、稳定运行。基于Python的流量分析算法,利用`scapy`等工具捕获和解析数据包,提取关键信息,区分正常与异常流量。结合机器学习和可视化技术,进一步提升内网监控的精准性和效率,助力企业防范潜在威胁,保障业务顺畅。本文深入探讨了Python在内网监控中的应用,展示了其实战代码及未来发展方向。
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
132 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2月前
|
存储 缓存 监控
局域网屏幕监控系统中的Python数据结构与算法实现
局域网屏幕监控系统用于实时捕获和监控局域网内多台设备的屏幕内容。本文介绍了一种基于Python双端队列(Deque)实现的滑动窗口数据缓存机制,以处理连续的屏幕帧数据流。通过固定长度的窗口,高效增删数据,确保低延迟显示和存储。该算法适用于数据压缩、异常检测等场景,保证系统在高负载下稳定运行。 本文转载自:https://www.vipshare.com
132 66
|
7天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
28 10
|
25天前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
50 17
|
1月前
|
存储 监控 算法
员工电脑监控屏幕场景下 Python 哈希表算法的探索
在数字化办公时代,员工电脑监控屏幕是保障信息安全和提升效率的重要手段。本文探讨哈希表算法在该场景中的应用,通过Python代码例程展示如何使用哈希表存储和查询员工操作记录,并结合数据库实现数据持久化,助力企业打造高效、安全的办公环境。哈希表在快速检索员工信息、优化系统性能方面发挥关键作用,为企业管理提供有力支持。
45 20
|
28天前
|
存储 人工智能 算法
深度解密:员工飞单需要什么证据之Python算法洞察
员工飞单是企业运营中的隐性风险,严重侵蚀公司利润。为应对这一问题,精准搜集证据至关重要。本文探讨如何利用Python编程语言及其数据结构和算法,高效取证。通过创建Transaction类存储交易数据,使用列表管理订单信息,结合排序算法和正则表达式分析交易时间和聊天记录,帮助企业识别潜在的飞单行为。Python的强大功能使得从交易流水和沟通记录中提取关键证据变得更加系统化和高效,为企业维权提供有力支持。
|
1月前
|
JSON 安全 中间件
Python Web 框架 FastAPI
FastAPI 是一个现代的 Python Web 框架,专为快速构建 API 和在线应用而设计。它凭借速度、简单性和开发人员友好的特性迅速走红。FastAPI 支持自动文档生成、类型提示、数据验证、异步操作和依赖注入等功能,极大提升了开发效率并减少了错误。安装简单,使用 pip 安装 FastAPI 和 uvicorn 即可开始开发。其优点包括高性能、自动数据验证和身份验证支持,但也存在学习曲线和社区资源相对较少的缺点。
81 15

热门文章

最新文章

  • 1
    Burp Suite Professional 2025.2 (macOS, Linux, Windows) - Web 应用安全、测试和扫描
    23
  • 2
    AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
    19
  • 3
    【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
    53
  • 4
    部署使用 CHAT-NEXT-WEB 基于 Deepseek
    288
  • 5
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    26
  • 6
    java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
    37
  • 7
    零基础构建开源项目OpenIM桌面应用和pc web- Electron篇
    27
  • 8
    【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
    20
  • 9
    FastAPI与Selenium:打造高效的Web数据抓取服务 —— 采集Pixabay中的图片及相关信息
    53
  • 10
    springSecurity学习之springSecurity过滤web请求
    59