用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api
目前正在使用asp.net core 2.0 (主要是web api)做一個(gè)項(xiàng)目, 其中一部分功能需要使用js客戶端調(diào)用python的pandas, 所以需要建立一個(gè)python 的 rest api, 我暫時(shí)選用了hug, 官網(wǎng)在這: http://www.hug.rest/.
目前項(xiàng)目使用的是identity server 4, 還有一些web api和js client.
項(xiàng)目的早期后臺(tái)源碼:?https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplate
下面開始配置identity server 4, 我使用的是windows.
添加ApiResource:
在 authorization server項(xiàng)目中的配置文件添加紅色部分, 這部分就是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配置選項(xiàng):
添加 hugapi, 與authorization server配置對(duì)應(yīng).
{
? ? ? ? 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然后在某個(gè)地方建立一個(gè)目錄:
mkdir hugapi && cd hugapi建立虛擬環(huán)境:
virtualenv venv激活虛擬環(huán)境:
venv\Scripts\activate然后大約這樣顯示:
安裝hug:
pip install hug這時(shí), 參考一下hug的文檔. 然后建立一個(gè)簡單的api. 建立文件main.py:
import hug@hug.get('/home')def root(): return 'Welcome home!'運(yùn)行:
hug -f main.py結(jié)果好用:
然后還需要安裝這些:
pip install cryptography pyjwt hug_middleware_cors其中pyjwt是一個(gè)可以encode和decode JWT的庫, 如果使用RS256算法的話, 還需要安裝cryptography.?
而hug_middleware_cors是hug的一個(gè)跨域訪問中間件(因?yàn)閖s客戶端和這個(gè)api不是在同一個(gè)域名下).
添加需要的引用:
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來找到j(luò)wks_uri,
identity server 4 的discovery endpoint的地址是:
http://localhost:5000/.well-known/openid-configuration, 里面能找到各種節(jié)點(diǎn)和信息:
?
但我還是直接寫死這個(gè)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, 它的結(jié)構(gòu)是這樣的:
而我使用jwt庫, 的參數(shù)只能傳入一個(gè)證書的json, 也可就是keys[0].
所以上面的最后一行代碼顯得有點(diǎn).......
如果使用python-jose這個(gè)庫會(huì)更簡單一些, 但是在我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) 就會(huì)得到key (certificate), 然后通過jwt.decode方法可以把token進(jìn)行驗(yàn)證并decode, 算法是RS256, 這個(gè)方法要求如果token里面包含了aud, 那么方法就需要要指定audience, 也就是hugapi.
最后修改api 方法, 加上驗(yàn)證:
@hug.get('/home', requires=token_key_authentication)def root(): return 'Welcome home!'最后運(yùn)行 hug api:
hug -f main.py端口應(yīng)該是8000.
運(yùn)行js客戶端,登陸, 并調(diào)用這個(gè)hug api http://localhost:8000/home:
(我的js客戶端是angular5的, 這個(gè)沒法開源, 公司財(cái)產(chǎn), 不過配置oidc-client還是很簡單的, 使用)
返回200, 內(nèi)容是:?
看一下hug的log:
token被正確驗(yàn)證并解析了. 所以可以進(jìn)入root方法了.
?
其他的python api框架, 都是同樣的道理.
可以使用這個(gè)例子自行搭建 https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/7_JavaScriptClient?
官方還有一個(gè)nodejs api的例子:?https://github.com/lyphtec/idsvr4-node-jwks
相關(guān)文章:?
基于OIDC(OpenID Connect)的SSO
學(xué)習(xí)Identity Server 4的預(yù)備知識(shí)
使用Identity Server 4建立Authorization Server (1)
使用Identity Server 4建立Authorization Server (2)
使用Identity Server 4建立Authorization Server (3)
使用Identity Server 4建立Authorization Server (4)
使用Identity Server 4建立Authorization Server (5)
IdentityServer4(10)- 添加對(duì)外部認(rèn)證的支持之QQ登錄
spring cloud+.net core搭建微服務(wù)架構(gòu):Api授權(quán)認(rèn)證(六)
原文地址:https://www.cnblogs.com/cgzl/p/8270677.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Quartz.NET 3.0 正式发布
- 下一篇: [翻译] 比较 Node.js,Pyth