基于Oauth2协议的服务器的实现
库的使用:django-oauth-toolkit
语言: python
框架: django
ubuntu18.4
之前非常简单的写了客户端,然后今天把客户端和服务器的实现一起总结一下
实现原理:
1 客户端发送请求到第三方服务器,将请求转到认证服务器上
2 认证服务器返回用户登录页面,如果用户登录并确定授权后,认证服务器给客户端发送授权码,
3 客户端拿着code去向认证服务器交换access_token
4 客户端拿到access_token后访问资源服务器,资源服务器将客户端发送的信息转到认证服务器上进行验证,如果成功,资源服务器向客户端发送资源
为了观看方便
客户端我在文中用client表示
第三方就用第三方
第三方认证服务器用 auth server
第三方资源服务器用 res server
用户用user来表示
这里面基本上都是oauth2_provider提供的template
第一步骤:配置环境
pip install django-oauth-toolkit django-cors-middleware
创建三个django项目
1 创建auth server
django-admin startproject Django-oauth-project
cd Django-oauth-project
django-admin startapp Django-oauth-app
2 创建client
django-admin startproject client_project
cd client_project
django-admin startapp client_app
3 创建res server
django-admin startproject Resource_project
cd Resource_project
django-admin startapp Resource_app
创建完成之后开始配置setting.py文件(rs server/ auth server)
首先: auth server
在INSTALLED_APPS={
'oauth2_provider',
'corsheaders',
}
在urls.py中配置
urlpatterns = [
url(r"^admin/", admin.site.urls)),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), # ...
]
包括CORS中间件MIDDLEWARE = (
# ...
'corsheaders.middleware.CorsMiddleware',
# ...
)
# Or on Django < 1.10: MIDDLEWARE_CLASSES =
(
# ...
'corsheaders.middleware.CorsMiddleware',
# ...
)
同意从所有域的CORS 请求
CORS_ORGIN_ALLOW_ALL= True
到这这部分的配置配置完成
然后执行
python manage.py makemigrations
python manage.py migrates
当我们在完成配置后auth server就可以提供接口来让client来进行访问
因为上面我们已经配置好了服务器端的配置,因为直接调用的库,所以可以直接可以让用户进行第三方提供的API接口进行访问
第三方提供的接口:
oauth2_provider库提供的url
各个url的作用已经url后面做了注释
base_urlpatterns = [
url(r"^authorize/$",views.AuthorizationView.as_view(),name="authorize"), # 获取codeurl(r"^token/$",views.TokenView.as_view(),name="token"), // 获取access_tokenurl(r"^revoke_token/$",views.RevokeTokenView.as_view(),name="revoke-token"), #用户撤销access_token(登出)url(r"^introspect/$",views.IntrospectTokenView.as_view(),name="introspect"), # 获取数据]
management_urlpatterns = [# Application management viewsurl(r"^applications/$",views.ApplicationList.as_view(),name="list"), # 开发者访问application页面url(r"^applications/register/$",views.ApplicationRegistration.as_view(),name="register"), #开发者创建新的applicationurl(r"^applications/(?P[\w-]+)/$",views.ApplicationDetail.as_view(),name="detail"), # 查看某一个application的详细信息url(r"^applications/(?P[\w-]+)/delete/$",views.ApplicationDelete.as_view(),name="delete"), # 删除某个applicationurl(r"^applications/(?P[\w-]+)/update/$",views.ApplicationUpdate.as_view(),name="update"), # 编辑某个application# Token management viewsurl(r"^authorized_tokens/$",views.AuthorizedTokensListView.as_view(),name="authorized-token-list"), # 开发者查看 已经存在的access_tokenurl(r"^authorized_tokens/(?P[\w-]+)/delete/$",views.AuthorizedTokenDeleteView.as_view(), # 开发者删除选中的tokenname="authorized-token-delete"),]
第二步骤:在第三方开发者平台申请client_id, client_secret,这是为了让auth
server分辨你是哪个app
一个用户一个账户可以创建多个application,因为你不可以就写一个app
实现:用户用第三方的账号密码登录第三方应用,没有可以注册
客户端发送url : http://127.0.0.1:8000/o/applications/
如果用户没有在开发者平台登录,则会转到登录页面
相应的url会变成 http://127.0.0.1:8000/accounts/login/?next=/o/applications/
操作截图:(next 是我自己输出的) register是我自己加上的功能,是为了用户注册第三方账号
输入账号密码, 当用户登录之后,会显示所有的applications, 如果想创建新的application,可以点击new
application进行创建
---创建application 点击new application
name: 随便写
client_id/client_secret : 是第三方返回的内容,也就是客户端要记下来的东西
client_type: confidential
Authorization grant type : Authorization code
(意思是授权码模式进行认证)
Redirect url :
写你自己要进行处理第三方返回的内容的函数,比如处理返回的code 和access_token
等信息(我是这样理解的,如果有错请指正)
填写完毕后点击save
如果想对某个已经创建的app进行操作,点击这个app,进入这个app的详情页面,在这里面你也能看到这个app的client_id和client_secret,这时候你能看到三个按钮,go
back是返回按钮,Edit是编辑按钮,delete是删除按钮
创建完成之后,客户端开发者人员就可以写代码进行授权服务了.
如果客户端开发者要进行请求获取code\access_token等信息,一般都会在第三方上找到它提供的api接口,关于api接口我们上面已经写过了,在这里直接进行使用
1 获取code
代码:
可以看到我们发送的url是 /o/authorize/
参数 client_id(就是之前我们在开发者平台进行申请后第三方返回的client_id),
response_type:这个一定要写
state: 可以填写随意值
scope:范围 这里我没有写,默认是赋予客户端第三方支持的所有权限
这时候会访问到auth server ,然后进行登录并授权
这时候如果auth
server认证成功,则会返回给客户端code,返回的路由就是开发者申请application的时候填写的redirect_url
客户端处理code代码:
ifrequest.GET:
code = request.GET['code']
得到的code是有过期时间的,而且时间不长,并且只能用一次
2 access_token的生成
得到code之后,开发者要拿着code去交换token
访问的url为: /o/token
实现代码:
url = "http://127.0.0.1:8000/o/token/"
params = {
'content-type':'application/x-www-form-urlencoded','grant_type':"authorization_code",'code': code,'redirect_uri':"http://127.0.0.1:8001/client/callback",}
respone = requests.post(url,data=params,auth=(client_id,client_secret))
result = respone.json()
access_token = result["access_token"]
3 如果用户想登出撤销授权时
则调用/o/revoke_token/即可
4 此时access_token已经拿到了,然后开始访问资源
rs server还没有配置完整,需要先在auth server
上注册application,获取client_id和client_secret
rs server 还需要在settings里配置:
OAUTH2_PROVIDER = {
'RESOURCE_SERVER_INTROSPECTION_URL''http://127.0.0.1:8000/o/introspect/',
'RESOURCE_SERVER_AUTH_TOKEN':'3yUqsWtwKYKHnfivFcJu',
也可以将'RESOURCE_SERVER_AUTH_TOKEN':'3yUqsWtwKYKHnfivFcJu',
换成
#
'RESOURCE_SERVER_INTROSPECTION_CREDENTIALS':
('rs_client_id','rs_client_secret'),
需要在资源服务器上的配置与认证服务器的配置一样,其中资源和认证服务器都需要加上
'SOPES': {'read': 'Read scope','write': 'Write scope','introspection': 'Introspect token scope'}
客户端访问的url是rs server提供的url ,这里rs server提供的是/rs/my_view/
代码:
headers = {'client_id': client_id,'Authorization': 'Bearer '+ access_token,}
res = requests.get("http://127.0.0.1:8002/rs/my_view/",headers=headers)
这个接口的作用原理是当资源服务器通过客户端发送的access_token来进行验证,如果资源服务器查找不到,则发送给认证服务器进行验证/o/introspect/接口
如果验证通过,就可以返回给客户端所请求的资源