使用Django实现微信公众号用户openid登录认证

最近在用Django做一个小项目,需要将微信的用户与网站的用户进行关联,由于是微信的订阅号,没有oauth网页授权的权限,只能退而求其次,在响应中获取用户的openid,来唯一的标识用户。

Django中用户的模型继承和扩展于AbstractUser,在用户模型中添加openid字段(models.py):

class Users(AbstractUser):
    openid = models.CharField(max_length=100,blank=True,null=True,verbose_name="openid",unique=True)

我们扩展了用户的模型,并使用这个模型来作为用户认证的模型,需要在setting.py文件里指定认证的模型(website是django应用的名称,非项目名称):

AUTH_USER_MODEL = 'website.Users'

这样,我们就能够使用上面定义的Users模型来进行用户的登录和注册操作了。

一个常见默认的Django登录认证,使用的是authenticate,在此引用Django文档中的叙述:

认证一个给定用户名和密码,请使用authenticate() 它以关键字参数形式接收凭证,对于默认的配置它是username 和password,如果密码对于给定的用户名有效它将返回一个User对象。 如果密码无效,authenticate()返回None。 例子: from django.contrib.auth import authenticate user = authenticate(username='john', password='secret') if user is not None: if user.is_active: print("User is valid, active and authenticated") else: print("The password is valid, but the account has been disabled!") else: print("The username and password were incorrect.")

如果authenticate返回正确的User对象,我们再使用login()方法,对返回的User对象进行登录:

from django.contrib.auth import login
login(request,user)

这样就完成了一个最基本的Django用户认证。

如果我们要用其他的方式进行登录认证呢,比如电子邮箱、手机号、或是本文所说的重点:微信openid,那就需要自定义认证方式。

在Django中进行自定义认证很是方便,完成一个自定义的认证只需要三步:

1、编写一个认证后端:

一个认证后端是个实现两个方法的类: get_user(user_id)和authenticate(**credentials) 在此,我们新建一个py文件wechatAuth.py来写openid的认证后端:

from .models import Users'''
    微信openid认证登录
'''class WechatOpenidAuth(object):
    def get_user(self,id_):
        try:            
            return Users.objects.get(pk=id_)        
        except Users.DoesNotExist:            
            return None

    def authenticate(self,openid=None):
        try:
            user = Users.objects.get(openid=openid)            
            if user is not None:                
                return user            
            else:
                return None
        except Users.DoesNotExist:            
                return None

2、在配置文件setting.py中指定认证后端:

在底层,Django 维护一个“认证后台”的列表。 当调用django.contrib.auth.authenticate() 时,Django 会尝试所有的认证后台进行认证。 如果第一个认证方法失败,Django 将尝试第二个,以此类推,直至试完所有的认证后台。 使用的认证后台通过AUTHENTICATION_BACKENDS 设置指定。

AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', 
'website.wechat_auth.WechatOpenidAuth',)

第一个认证后端是Django默认的认证方式,因为在Web端还需要使用,所以保留,第二个就是基于openid的认证后端。

3、使用自定义的认证后端处理登录授权:

同样的使用authenticate()方法和login()方法,但是我们只传入一个参数进去,就是openid

from django.contrib.auth import login,authenticatedef auth(request,openid):
  try:
        auth =authenticate(openid=openid)
        login(request,auth)
        print("登录成功",auth)  
  except Exception as e:
        print(e)

这样,一个基于openid的认证就完成了。

在微信的订阅号中,我们可以利用click事件返回一个文本消息或图文消息,在其链接之中带上openid的参数。这样,当用户点击链接,就可以静默地完成用户的登录了。

原文发布于微信公众号 - 州的先生(zmister2016)

原文发表时间:2017-04-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏后端技术探索

Nginx从入门到学会(4.事件处理)

有人可能要问了,nginx采用多worker的方式来处理请求,每个worker里面只有一个主线程,那能够处理的并发数很有限啊,多少个worker就能处理多少个并...

601

Kafka体系结构:日志压缩

这篇文章是从我们介绍Kafka 体系结构的一系列文章中获得的启发,包括Kafka topic架构,Kafka生产者架构,Kafka消费者架构和Kafka生态系统...

2143
来自专栏从零开始学自动化测试

pytest文档12-skip跳过用例

pytest.mark.skip可以标记无法在某些平台上运行的测试功能,或者您希望失败的测试功能

1253
来自专栏Python小屋

Python使用标准库urllib模拟浏览器爬取网页内容

爬取网页内容的第一步是分析目标网站源代码结构,确定自己要爬取的内容在哪里,这要求对HTML代码有一定了解,对于某些网站内容的爬取还需要具有一定的Javascri...

551
来自专栏菩提树下的杨过

ssh 免密码设置失败原因总结

先复习一下设置ssh免密码操作的步骤: 进入主目录 cd 生成公钥 ssh-keygen -t rsa -P '' (注:最后是二个单引号,表示不设置密码) 然...

1778
来自专栏Java成神之路

Git_学习_00_资源帖

3.Git简明教程 : https://rdc.hand-china.com/gitlab/HAP/hap-developer-guide/blob/maste...

782
来自专栏phodal

如何以“正确的姿势”阅读开源软件代码

之前想过写这篇文章,但是没有想到一个好的内容、好的突破点。在《GitHub 漫游指南》指南里,我们提到过《如何在GitHub“寻找灵感(fork)”》,但是并不...

17810
来自专栏精讲JAVA

Java新一代网络编程模型AIO原理及Linux系统AIO介绍

从JDK 7版本开始,Java新加入的文件和网络io特性称为nio2(new io 2, 因为jdk1.4中已经有过一个nio了),包含了众多性能和功能上的改进...

2138
来自专栏WindCoder

AdminLTE实现动态菜单

本篇内容基于上一篇AdminLTE实现局部刷新,在完成局部刷新后,不满足其左侧菜单栏的写死状态,希望后期能从数据库读取动态生成,故有了本篇尝试。

4280
来自专栏智能计算时代

Envoy架构概览(8):统计,运行时配置,追踪和TCP代理

统计 特使的主要目标之一是使网络可以理解。特使根据配置如何发出大量的统计数据。一般来说,统计分为两类: 下游:下游统计涉及传入的连接/请求。它们由侦听器,HTT...

3815

扫码关注云+社区