• Django OAuth Toolkit


    使用说明

    B依托Django OAuth Toolkit, 具备作为OAuth2.0服务器能力, 第三方网站/系统/服务/APP, 可以利用该能力, 获取用户登录信息, 各类资源.

    假设你拥有一个系统A, 希望在系统A的导航条中增加一个按钮, “使用B登录”, 点击后, 用户可以利用B帐号登录系统A, 并获取用户信息和B可向系统A暴露的其他信息.

    具体来说, 用户会访问系统A(a), 点击”使用B登录”, 并被跳转到B登录页(b), 如果用户没有登录B, 需要输入用户名密码, 否则用户被询问是否允许使用B帐号登录系统A(c), 用户点击允许, 并跳转回系统A(d), 系统A获得Token, 可以访问用户信息等B接口(e).

    了解一些背景知识

    OAuth2.0是一种非常通用的工业级授权方式(OAuth 2.0 is the industry-standard protocol for authorization.) 如果你从未听过, 可以参考下列资料做一个粗略了解:

    在B注册系统A

    注册并登录B.

    打开OAuth应用注册页面 你的服务地址/oauth2/applications/, 点New Application

    其中Name填自己的应用名称, Client id和Client secret可以用自动生成的.

    • name:应用名称

    • Client id、Client secret自动生成

    • Client type :公开还是机密

    • Authorization grant type 一共有四种

      • 授权码(authorization-code):指的是第三方应用先申请一个授权码,然后再用该码获取令牌,这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。一般针对于用户。此种方式见后面详细介绍。

      • 隐藏式(implicit):有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端

      • 密码式(password):如果你高度信任某个应用,也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌

      • 客户端凭证(client credentials):最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

        可直接通过client_id和secret直接获取token

        # body
        {
        	"client_id": "xxx",
        	"client_secret": "xxx",
        	"redirect_uri": "http://django-oauth-toolkit.herokuapp.com/consumer/exchange/",
        	"grant_type": "client_credentials"
        }
        
    • Redirect uris:访问以后跳转的地址。

    授权码(authorization-code)方式

    授权码方式使用

    所谓落地页, 就是访问授权后用户回到的页面.

    如果你还没开始开发, 可以先用这个网站试一试, 本页面会生成一个链接,点击后会跳转到授权页面。

    在例子中, 落地页应该填: http://django-oauth-toolkit.herokuapp.com/consumer/exchange/

    最后点保存, 就完成了B侧的应用注册.

    显然, 你需要记下来自己的Client id和Client secret.

    用户将看到一个这样的页面(可以通过django国际化进行汉化):

    用户点击授权之后, 将会被重定向到你的落地页, 并在url中携带code

    在例子中, 应该在该页面, 输入你的Client id和授权url: 你的域名/oauth2/authorize
    , 然后获得重定向地址, 并跳转到如下页面

    你的落地页后端拿到code之后, 需要请求token, 也就是你的落地页后端需要发一个POST请求:

    fetch(new Request('你的域名/oauth2/token/',{
        method:'POST', 
        headers: {'Cache-Control': 'no-cache',
                'Content-Type':'application/x-www-form-urlencoded'},
        body:{
            'client_id':'3RGYcLX5nj9vMT0UbjxjXmYikNrOwEEH2uofF6gq',
    'client_secret':'Wu0tcWSpPk3AqUVw1FFS7zWuibEOxELlCp8AtQDPfq2qo991eH8oIGluFSDStEO80ndzWV32e5szIpyNWM5auj8HFTFrzqqnmYo5pYzuI6fFcKdfj90blHgMYivAgWLp',
            'code':'yiKoD7Ms1EvE2dgj5dP51MepkJPFty',
            'redirect_uri':'http://django-oauth-toolkit.herokuapp.com/consumer/exchange/',
            'grant_type':'authorization_code'
        }
    })).then((resp)=>{console.log(resp)})
    

    这一步的目的是将明文传输的CODE换成服务器之间传递的TOKEN, 你可以开发另一个落地页2, 或者通过参数复用同一个落地页, 为防混乱, 在本文档中, 我们使用落地页2描述上述POST请求中的${YOUR_CALLBACK_PAGE}

    在例子中, 你需要60秒内手动发送上述POST请求, 但是在正式集成中, 应该由落地页的后端自动发送, 按F12打开浏览器调试工具, 填上一个图片中右边的表单, token url是你的域名/oauth2/token/ 点Submit, 就能看到你发出了上述POST请求.

    上述POST将给你如下返回值:

    {
    	"access_token": "aVvBRVFMWPYhZPczNlaWdPTyT5g8Fk",
    	"expires_in": 36000,
    	"token_type": "Bearer",
    	"scope": "read write"
    }
    

    凭上述access_token, 用户可以访问B中该用户全部授权资源, 例如, 落地页2应该访问下面API, 获取并展示用户信息, 完成系统A的登录:

    跳过授权码

    该方式需要你完全信任对方,可避免弹窗出现。在Applications的model中将skip_authorization = True,可在admin的后台操作。

    获取用户信息接口

    url: /api/v2/user/
    method: GET
    header:

    {"Authorization": "Bearer QUgU1t5MvaRuuMtaGy8gTCm3dtdGGL"}
    

    Response

    {
    		"email": "dfsdfzza@phytium.com.cn",
    		"password": "123",
    		"last_login": null,
    		"username": "fgfdsaasd",
    		"last_name": "发给对方",
    		"date_joined": "2020-07-23T02:12:34.588741"
    	}
    

    后端代码

    这样就能返回用户自己的信息了。

    class UsersSerializer(serializers.ModelSerializer):
        class Meta:
            model = Users
            fields = '__all__'
            depth = 1
    
    
    class UserDetail(generics.GenericAPIView):
        authentication_classes = [OAuth2Authentication]
    
        def get(self, req, *args, **kwargs):
            user = req.user.users
            serializer = UsersSerializer(instance=user)
            data = serializer.data
            data['user'].pop('password')
            return Response(serializer.data)
    
  • 相关阅读:
    css: 组合选择器
    css: 基础选择器
    javascript设计模式:工厂模式
    wx: 小程序公共机制
    vue: 脚手架创建项目
    nodejs: express sequelize-cli
    css:flex和float margin布局
    自定义标签之inclusion_tag
    Django模型之Meta选项详解
    Django内置Admin
  • 原文地址:https://www.cnblogs.com/liuweida/p/16291976.html
Copyright © 2020-2023  润新知