Django实现oauth登录-以微博为例

作为一个菜鸟,一直想了解并想实现一下通过oauth登录自己的网站,加上最近工作中需要了解oauth,借此把最近的理解和简单的实现记录下来,防止以后忘记。

什么是oauth:

在我的理解里,oauth就是不通过本地的用户信息,而是通过微博,微信等第三方的用户信息登录到自己的网站中。oauth授权有多种模式,我最近了解的是授权码授权模式,微博的oauth2.0授权登录也是根据这个模式。其他模式可以看https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html,说得很详细,也容易懂。

步骤:

在我的实现中,一共五个步骤:

1、获取授权码code

2、通过授权码code获取认证码access_token

3、通过acess_token获取微博端的用户信息

4、根据步骤3的用户信息,与本地数据库的用户信息对比,实现本地登录操作

5、登录完成,跳转网页

接下来,会根据以上5个步骤,结合微博授权登录,给出用django实现的代码与说明

准备工作:

先到http://open.weibo.com/微博开放平台,依次点击网站接入-立即接入(记得要先登录再点击,要不会没有反应),注册一个应用,获取app key和app secret,这两个东西是步骤1、2中的关键参数。

当你登录并创建应用后,可以在 我的应用-应用信息-基本信息 中找到这两个东西,接下来就可以进行开发了。

1、获取授权码code:

我们可以在很多网站的登录页看到QQ,微博等登录图标,当我们点一下,就会弹框或跳转到相应的第三方登录页,然后输入QQ或微博账号,登录成功后会再跳转到某个页面,这当中就包含了获取授权码code的过程了。我们先创建一个页面login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="https://api.weibo.com/oauth2/authorize?client_id=app_key&response_type=code&redirect_uri=http://127.0.0.1:8000/process">
    微博登录
</a>
</body>
</html>

这里的微博登录可以换成微博小图标,点击就会跳转到微博的登录页。这里解释一下参数,client_id的值就是准备工作中得到的app key,response_tye为固定值,redirect_uri的值为登录成功后要跳转的页面,一般来说,这个值不会是最终要跳转的页面,而是作为一个中间值,用来处理微博用户信息与本地用户信息的关系,并实现本地的登录。视图函数中的代码:

def login(request):
    return render(request, "login.html")

很简单的一个函数,仅仅是渲染一下登录页面。

当在微博登录页登录成功后,会以redirect_uri?code=xxxx(本例子中为

http://127.0.0.1:8000/process?code=xxxxx

)的方式回调你所填的uri,这时就可以获取到授权码code了,需要注意的是,回调的redirect_uri需要在 我的应用-应用信息-高级信息-OAuth2.0 授权设置中进行设置,要不回调时会报错。

2、获取acess_token:

acess_token不仅仅可以用来获取微博的用户信息,还可以调用微博提供的其他api,详情可以看官方文档http://open.weibo.com/wiki/。首先看获取token的代码:

def get_token(code):
    """
    获取access_token
    http://open.weibo.com/wiki/Oauth2/access_token
    """
    app_key = app_key
    app_secret = app_secret
    token_url = "https://api.weibo.com/oauth2/access_token"
    params = {
        "client_id": app_key,
        "client_secret": app_secret,
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "http://127.0.0.1:8000/process"
    }
    result = requests.post(url=token_url, data=params)
    return result

主要看params中的参数,这些都是获取access_token的必须参数,code为步骤1中获取到的授权码,grant_type在授权码模式中就是这个固定值,redirect_uri要与步骤1中的一样,详情可看文档 http://open.weibo.com/wiki/Oauth2/access_token,返回的结果如下:

{'access_token': 'xxxxxxxxxx', 'remind_in': '157679999', '
expires_in': 157679999, 'uid': '392039283', 'isRealName': True}

uid是登录微博用户的id,可以通过这个获取用户信息,其他返回参数意义可看官方文档。

3、获取用户信息:

直接上代码:

文档https://api.weibo.com/2/users/show.json

def get_user_info(result):
    """
    获取用户信息
    """
    get_user_url = "https://api.weibo.com/2/users/show.json"
    uid = result["uid"]
    access_token = result["access_token"]
    user_info = requests.get(url=get_user_url, params={"access_token": access_token, "uid": uid})
    return user_info

函数参数中的result是步骤2中的result,获取用户信息的必要两个参数是access_token和uid

4、实现本地登录:

本地登录不是必须的,你可以在微博端认证完毕后,不再在本地进行验证,而直接设置cookies,然后跳转到最后的登录页,比如网站的首页。我们这里不这样做,而是进行本地验证,代码如下:

def process(request):
    code = request.GET.get("code")
    result = get_token(code)  # 获取access_token和用户uid
    result = result.json()  # 将json格式字符串转化为字典对象

    user_info = get_user_info(result).json()
# 接下来是你的网站的登录处理,你有两种选择:
    #   1、你可以不做任何处理,只要用户成功登录了微博,就直接跳转到你的网站首页。
    #   2、你可以对比本地数据库,看是否存在该用户,如果存在则直接跳转,不存在可以提示用户绑定你的网站的账号,或者直接用
    #       微博用户信息作为该用户在你本地的账号
    return redirect("/index")

这是一个视图函数,是处理步骤1中http://127.0.0.1:8000/process,这个回调uri的,可以看到我们获取了授权码code,然后获取access_token和uid(步骤2),接着获取用户信息(步骤3),接下来的验证要根据自己的实际情况进行。最后所有东西处理完毕后,重定向到首页index去。

 

最后是django,urls.py中的代码:

from django.conf.urls import url
from django.contrib import admin
from  django_app import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^process/', views.process),
    url(r'^index/', views.index),
]

 

最后总结一下,在用户看来,整个过程只有两步,第一步是跳转到微博登录页,用户输入账号密码;第二步是跳转到指定url(这个url不是redirect_uri),这个url可以是网站首页,也可以是绑定本地网站账号页,用户是看不到跳转redirect_url即http://127.0.0.1:8000/process这个步骤的,这个步骤是给我们处理一些东西用的。

 

以上仅仅是我个人的理解,也是第一次写博客,如果有写得不好或写错的地方,欢迎指出

posted @ 2018-07-17 23:40  Wweic  阅读(2992)  评论(1编辑  收藏  举报