博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api
阅读量:5865 次
发布时间:2019-06-19

本文共 6326 字,大约阅读时间需要 21 分钟。

[新添加] 本文对应的源码 (多个flow, clients, 调用python api): 

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

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

项目的早期后台源码: 

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

添加ApiResource:

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

public static IEnumerable
GetApiResources() { return new List
{ 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 hugimport jwtimport jsonimport urllib.requestfrom jwt.algorithms import get_default_algorithmsfrom hug_middleware_cors import CORSMiddleware

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

identity server 4 的discovery endpoint的地址是:

, 里面能找到各种节点和信息:

 

但我还是直接写死这个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 Falsetoken_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): 

可以使用这个例子自行搭建

官方还有一个nodejs api的例子: 

今日修改后的代码: 

import jsonimport hugimport jwtimport requestsfrom jwt.algorithms import get_default_algorithmsfrom hug_middleware_cors import CORSMiddlewareapi = 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 Falsetoken_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相关技术的公众号--草根专栏:

转载地址:http://ykfnx.baihongyu.com/

你可能感兴趣的文章
spring定时器----JobDetailBean
查看>>
我的友情链接
查看>>
XP下如何删除附件中的游戏组件
查看>>
Mysql提供sequence服务
查看>>
我的友情链接
查看>>
Git安装
查看>>
pandas和matplotlib和
查看>>
nginx开启core dump文件
查看>>
emma的几个不足之处
查看>>
Java工具类——UUIDUtils
查看>>
使用Node搭建reactSSR服务端渲染架构
查看>>
文件缓存
查看>>
生成固定大小的占位图片
查看>>
作业五 :团队项目准备素材搜集
查看>>
转 博弈类题目小结(hdu,poj,zoj)
查看>>
Java NIO学习笔记八 Pipe
查看>>
远程协助
查看>>
Scrum实施日记 - 一切从零开始
查看>>
关于存储过程实例
查看>>
配置错误定义了重复的“system.web.extensions/scripting/scriptResourceHandler” 解决办法...
查看>>