[新添加] 本文对应的源码 (多个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 = * ,
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

用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api的更多相关文章

  1. Identity Server 4 从入门到落地(四)—— 创建Web Api

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  2. Identity Server 4 从入门到落地(三)—— 创建Web客户端

    书接上回,我们已经搭建好了基于Identity Server 4的认证服务和管理应用(如果还没有搭建,参看本系列前两部分,相关代码可以从github下载:https://github.com/zhen ...

  3. 使用PostMan Canary测试受Identity Server 4保护的Web Api

    在<Asp.Net Core: Swagger 与 Identity Server 4>一文中介绍了如何生成受保护的Web Api的Swagger文档,本文介绍使用PostMan Cana ...

  4. 第17章 社区快速入门和模板 - Identity Server 4 中文文档(v1.0.0)

    IdentityServer组织不维护这些示例.IdentityServer组织愉快地链接到社区模板,但不能对模板做出任何保证.请直接与作者联系. 17.1 各种ASP.NET核心安全样本 https ...

  5. Identity Server 4 从入门到落地(五)—— 使用Ajax访问Web Api

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  6. Identity Server 4 从入门到落地(六)—— 简单的单页面客户端

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  7. Identity Server 4 从入门到落地(七)—— 控制台客户端

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  8. Identity Server 4 从入门到落地(八)—— .Net Framework 客户端

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  9. Identity Server 4 从入门到落地(九)—— 客户端User和Role的解析

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

随机推荐

  1. JS排序

    冒泡排序 https://sort.hust.cc/1.bubbleSort.html 选择排序 https://sort.hust.cc/2.selectionSort.html 插入排序 http ...

  2. HTML: width,height

    在进行前端页面开发时,width(width,offsetWidth,scrollWidth,clientWidth)height(height,offsetHeight,scrollHeight,c ...

  3. python小整数与str数据池,编码关系

    1.小数据池:数字,字符串 数字的范围-5 ---256 字符串:1,不能有特殊字符 2,s*20 还是一个地址,s*21以后都是两个地址 2.编码关系:ascii A : 00000010 8位 一 ...

  4. dubbo服务治理中间件,zookeeper注册中心

    对传统项目架构进行拆分: 集群概念: 面向服务分布式架构: 服务层提供被注册的对象需要实现序列化接口Serializable: 配置表现层和服务层: 依赖包: 服务层: <!-- 定义dubbo ...

  5. 《决战大数据:驾驭未来商业的利器》【PDF】下载

    内容简介 大数据时代的来临,给当今的商业带来了极大的冲击,多数电商人无不"谈大数据色变",并呈现出一种观望.迷茫.手足无措的状态.车品觉,作为一名经验丰富的电商人,在敬畏大数据的同 ...

  6. 《Spark大数据处理:技术、应用与性能优化》【PDF】

    内容简介 <Spark大数据处理:技术.应用与性能优化>根据最新技术版本,系统.全面.详细讲解Spark的各项功能使用.原理机制.技术细节.应用方法.性能优化,以及BDAS生态系统的相关技 ...

  7. UML2和建模工具学习总结

    软件发展的方向:CS–>BS–>SOA–>BIG DATA 建模的含义: 模型是对现实的简化 从特点视角对系统的一个完整性描述 建模的重要性: 为了更好的理解一个系统 管理复杂度(也 ...

  8. springboot 结合mybatis

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...

  9. [置顶] Xamarin android沉浸式状态栏

    虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...

  10. ArcGIS API for JavaScript 4.2学习笔记[14] 弹窗的位置、为弹窗添加元素

    这一节我们来看看弹窗的位置和弹窗上能放什么. 先一句话总结: 位置:可以随便(点击时出现或者一直固定在某个位置),也可以指定位置 能放什么:四种,文字.媒体(图片等).表格.附件. [Part I 位 ...