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

小说:神首集团靠什么赚钱作者:石卓顺华更新时间:2019-02-21字数:69767

随着星宿僧放出在种种异相,一个个的金色符文没入到绝心师太的元神之中,绝心师太元神之上的业力逐渐的被凝聚成了一个小小的黑色小球。绝心师太脸上的那种疯狂而痛苦的表情已然消失,取而代之的是一团祥和。

滴滴外地车还能接单吗

中年人微笑道:“这些服务员本身就都是属于拍卖场的,包括她们的生命。都是很小就被拍卖场买下的平民女子,从小进行培养。她们不但是这里的服务人员,同时也是拍卖的一部份。如果有人愿意出钱,她们是可以被买卖的。”
当他刚刚离开这座赌场后,那拉斯维加斯的警察便是赶到了。不光有普通的警察,还有一些全副武装的特勤人员,鱼贯进入到了赌场之中。

王小民摇头一笑道:“薛大哥,你就别笑话我了。其实我也没做什么,只是凭着本心,做一些自己力所能及,而且想做又有意义的事情罢了。”

目前正在使用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

激活虚拟环境:

venvScriptsactivate

然后大约这样显示:

安装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框架, 都是同样的道理.

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

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

编辑:龙帝扁建

发布:2019-02-21 04:52:53

当前文章:http://www.leetaemin.cn/content/201809/22/content_18114.html

上美团还需要交钱吗 北京春节前临时招聘 一般淘宝邮费多少钱 淘宝逆战接单 赚链 靠谱赚手赚网 叮咚众包佣金太少 南京美团外卖兼职待遇

77278 89758 44291 18650 44354 8616865285 34639 34955

我要说两句: (0人参与)

发布