用 Identity Server 4 来保护 Python web api

项目的早期后台源码: 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 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 = { $"/login-callback", $"/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:

运行:

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中间件:

然后是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

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

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

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

最后运行 hug api:

hug-fmain.py

端口应该是8000.

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

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

返回200, 内容是:

看一下hug的log:

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

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

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

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

本文来自企鹅号 - dotNET跨平台媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Grace development

PHP程序员必须知道的两种日志

作为一名程序员,比码代码还重要那么一点点的东西就是日志的分析和查询。下面列出常见日志及设置方法。

4003
来自专栏王硕

原 Windows 64位下 PostgreSQL的编译

38811
来自专栏晓晨的专栏

ASP.NET Core + Docker +Jenkins 实现持续集成

2152
来自专栏Python爬虫与算法进阶

强大的异步爬虫 with aiohttp

看到现在网络上大多讲的都是requests、scrapy,却没有说到爬虫中的神器:aiohttp

1562
来自专栏C/C++基础

DOS常用命令大全

2010-04-17 22:27:19|  分类: 电脑技术 |  标签:dos命令大全 |字号大中小 订阅

2021
来自专栏Java后端技术栈

基于Spring AOP和Groovy日志模板配置的日志记录框架的二次实现与使用案例

https://git.oschina.net/xuliugen/ufind-businesslog.git

1013
来自专栏程序猿成长计划

Linux命令必知必会

第一行中,03:30:22是当前时间,up 39 min是系统运行的运行了多长时间,1 user指出了当前有几个用户登录到系统,load average指的是系...

6054
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第七天 HTTP&Tomcat学习

HTTP协议:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。用于定义WEB浏览器与WE...

1855
来自专栏我是攻城师

Hadoop2.7.1和Hbase0.98添加LZO压缩

3157
来自专栏数据处理

ssh免密登陆上传下载文件直接使用scp命令

在滴滴云申请了三台服务器,分别命名Master,Worker1,Worker2,用来配置spark环境,需要在本地远程免密操作三台机器,首先在本地生成RSA公私...

1481

扫码关注云+社区

领取腾讯云代金券