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)
posted @ 2022-05-20 12:55  Lowell  阅读(1095)  评论(0编辑  收藏  举报