最近在项目中需要用到oauth2来进行第三方的授权服务,在网上了解到django-oauth-toolkit已经集成了oauth2方法,将自己心得记录下来.
首先要学习什么是oauth2,阮老师的介绍应该算是很详细了,网址为:理解oauth2.
我用到的是oauth2中的密码模式 resource owner password credentials来进行访问授权的,与授权码模式有所不同,不过大致原理相似,可以自行尝试.
============================================================================
2. 在服务器端临时设置了三个view,代码如下:
class ApiEndpoint(ProtectedResourceView):
def get(self, request, *args, **kwargs):
return HttpResponse('this is oauth2')
def index(request):
return HttpResponse('hello world!')
@login_required()
def secret_tag(request):
return HttpResponse('this is secret!',status=200)
一般情况下,当跨域访问index时,会被拒绝,实质是被浏览器阻挡.如果上面的设置成功,在主机上9000端口的客户端访问8000端口的服务器,则可以正常访问index
在setting.py中加入如下信息:
AUTHENTICATION_BACKENDS = (
'oauth2_provider.backends.OAuth2Backend',
# 上面这个就可以,不过建议加上下面这个,否则最后无法登录服务器上django后台admin
'django.contrib.auth.backends.ModelBackend'
'...',
)
同时,在middleware中加入如下中间件:
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
这两个有先后顺序,区别在于:
这样处理后的效果就是,利用curl -H "Authorization: Bearer
class AccessToken(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
on_delete=models.CASCADE)
token = models.CharField(max_length=255, unique=True)
application = models.ForeignKey(oauth2_settings.APPLICATION_MODEL,
on_delete=models.CASCADE)
expires = models.DateTimeField()
scope = models.TextField(blank=True)
...
为此,可以在服务器上修改ApiEndpoint,获取授权用户,从而进行更多操作,如下:
class ApiEndpoint(ProtectedResourceView):
def get(self, request, *args, **kwargs):
token_id=AccessToken.objects.get(token=request.GET['access_token'])
user=token_id.user
if user:
email = user.email
return HttpResponse(email)
return HttpResponse('you can access ,but no userinfo')
用此方法可以直接确认到该用户信息(这都是在服务器上进行的,不是客户端).通过debug调试发现一个有趣的事情, 当你用access_token来访问ApiEndpoint时,虽然是用匿名用户访问的,但是,在request中,oauth-toolkit会加入一个resource_owner字段,该字段指向该令牌的所有者user,也就是说我们可以用request.resource_owner来获取到user!,效果跟request.user一样.这样一来可以进行一次优化,不用访问数据库资源也可以确认用户,修改代码如下:
class ApiEndpoint(ProtectedResourceView):
def get(self, request, *args, **kwargs):
user = request.resource_owner
if user:
email = user.email
return HttpResponse(email)
return HttpResponse('you can access ,but no userinfo')
3. 客户端方面,用了一个前端页面来模拟客户端的请求授权,用到了ajax,跨域方法用cors来实现,而不是JSONP来进行的跨域请 求.前端代码由于是花一天左右时间学习并完成的,只是实现了访问获取的流程.对于client获取到资源后该如何使用,获取到的access_token以及过期时间,refresh_token如何保存等等,需要写专门的view来进行业务处理.前端代码如下:
client
This is http_webapp, a client
you can login or regist
login
regist
if you don't do that ,you can also tell us your username and password to access fk server
username:
password:
url: