一般情况下,在公众号里的菜单或绑定url的文字图片等,就是点击需要跳转到我们编写的网页上去的时候,直接绑定接口的外网访问地址就可以了。也就是说,在浏览器怎么访问,在微信里还是怎么访问。
但在微信里,如果没有域名,会弹出提示页面,要求用户绑定域名。
微信的网页授权登录,主要是针对登录页面,要验证用户身份。而这不是我们关心的,因为用户身份需要我们自己写程序去验证,如手机号验证。这个功能形同鸡肋。但微信网页授权的另一个功能是,只要这个网页通过了微信授权,就可以获取当前用户的所有资料,包括openid。
openid是公众号用户的唯一标识,把openid和手机号一起存在用户信息模型中,这样就可以随时获取用户信息了。
这种情况一般在注册或绑定手机号的页面使用。
网页授权的前提是:在接口权限表中设置网页授权获取用户信息中去修改服务器IP。测试账号,直接进入后下拉,正式账号在公众号首页/开发/接口权限中。
注:这里一般填服务器IP或域名,表示这个IP下所有url都是被微信允许授权的。
根据微信官网文档《微信网页开发/网页授权》,网页授权分为四步,我们把微信网页授权和工程授权结合起来,全面演绎登录授权的业务逻辑。
1 准备工作
准备两个网页,一是访问主页,二是登录页面。
1.1 登录页面,Applications/Organizations/Templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录页面</h1>
</body>
</html>
1.2 登录视图 Applications/Organizations/views/Login.py
from django.shortcuts import render
from rest_framework.views import APIView
class Login(APIView):
@classmethod
def get(cls, request):
"""
【功能描述】主要用于示例展示</br>
【返回参数】返回用户请求的网页</br>
"""
return render(request, 'login.html')
1.3 用户首页页面Applications/Organizations/Templates/user-home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户首页</h1>
</body>
</html>
1.4 用户首页视图Applications/Organizations/views/UserHome.py
from django.shortcuts import render
from rest_framework.views import APIView
from GeneralTools.AuthToken import decorate
from django.utils.decorators import method_decorator
@method_decorator(decorate, name='get')
class UserHome(APIView):
@classmethod
def get(cls, request):
"""
【功能描述】用户主页</br>
【返回参数】返回用户请求的网页</br>
"""
return render(request, 'user-home.html')
2 公共方法
登录验证需要四个公共方法
getToken:获取access_token,用户绑定手机号成功后,返回用户一个access_token,以后,用户携带access_token来访问工程中所有接口。
checkToken:检查access_token是否有效(被篡改或失效),如果有效,则把手机号存入session中,以便用户使用页面时,可以根据手机号获取用户权限或用户信息。
get_WeChatOAuth:拼接成微信授权回调url,用于微信网页授权时调用。
decorate:装饰器,用于对所有需要授权的网页进行认证。如果认证成功,则直接返回所访问的网页,如果认证失败,有两种情况:微信浏览器访问,则返回一个授权回调地址;其它浏览器访问,则直接返回需要访问的页面。
在GeneralTools下创建文件,名为:AuthToken.py,内容如下:
from django.shortcuts import redirect
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer
from itsdangerous import BadData
from TongHeng2 import settings
from . import Constents
from rest_framework.response import Response
from rest_framework import status
import logging
from wechatpy.oauth import WeChatOAuth
logger = logging.getLogger('tongheng2')
def getToken(openid, mobile):
"""
【功能说明】根据用户openid和mobile用于生成access_token
"""
tjwserializer = TJWSSerializer(
secret_key=settings.SECRET_KEY, # 密钥
salt=Constents.SALT, # 盐值
expires_in=Constents.VERIFY_ACCESS_TOKEN_EXPIRES # 有效期
)
access_token = tjwserializer.dumps({'openid': openid, 'mobile': mobile}) # bytes
access_token = access_token.decode()
return access_token
def checkToken(token, request):
"""
【功能说明】检查access_token是否正确
"""
tjwserializer = TJWSSerializer(
secret_key=settings.SECRET_KEY, # 密钥
salt=Constents.SALT, # 盐值
expires_in=Constents.VERIFY_ACCESS_TOKEN_EXPIRES # 有效期
)
try:
tjwdata = tjwserializer.loads(token)
# 如果验证成功,则把手机号存入到session里面,以便在页面中可以随时根据mobile获取用户信息和权限。
mobile = tjwdata['mobile']
request.session['mobile'] = mobile
return True
except BadData as e:
logger.error(e)
return False
def get_WeChatOAuth(redirect_uri, state='123', scope='snsapi_userinfo'):
"""
获取WeChatOAuth对象
:param redirect_uri: 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
:param scope:应用授权作用域,snsapi_base,snsapi_userinfo
:param state:重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
:return: WeChatOAuth对象
"""
return WeChatOAuth(
app_id=Constents.WECHAT_APPID,
secret=Constents.WECHAT_APPSECRET,
redirect_uri=redirect_uri,
scope=scope,
state=state
)
# 装饰器
def decorate(func):
def wrapper(request, *args, **kwargs):
# 从用户session中,获取access_token
access_token = request.session.get('access_token', None)
if access_token and checkToken(access_token, request):
# 如果access_token存在,且正确,则直接执行下一步
return func(request, *args, **kwargs)
else:
# 如果access_token不存在,或不正确
userAgent = str(request.META['HTTP_USER_AGENT']) # 获取访问浏览器的类型
if userAgent.find('MicroMessenger') < 0: # 如果不是微信浏览器,则直接跳转到登录页面
return redirect('/Organizations/Login/')
else: # 如果是微信浏览器,返回微信授权回调地址,前端根据地址,调用login登录页面。
url = get_WeChatOAuth(Constents.REDIRECT_URI).authorize_url
return Response(data={'url': url}, status=status.HTTP_201_CREATED)
return wrapper
3 添加装饰器
把装饰器添加到需要验证的页面上。
打开Applicatoins/Organizations/views/UserHome.py
from django.shortcuts import render
from rest_framework.views import APIView
from GeneralTools.AuthToken import decorate
from django.utils.decorators import method_decorator
@method_decorator(decorate, name='get')
class UserHome(APIView):
@classmethod
def get(cls, request):
"""
【功能描述】用户主页</br>
【返回参数】返回用户请求的网页</br>
"""
return render(request, 'user-home.html')
4 服务器发布工程
由于微信公众号网页授权必须要有公网IP,故需要在服务器发布。
发布后在微信中访问,则显示以下页面,而在其它浏览器访问,则直接显示登录页面。

此时,前端得到了授权回调地址,把这个地址拷贝到微信执行,可看到登录
5 编写登录视图
登录视图的思路如下:
获取code和state:如果code不存在,表示不是微信浏览器访问,则返回一个空的用户信息
如果code存在,则根据state重新获取wechatOAuth对象
把code传入wechatOAuth对象,获取access_token
刷新access_token
获取用户微信信息,并把这个信息返回前端。.
from django.shortcuts import render
from rest_framework.views import APIView
from GeneralTools.AuthToken import get_WeChatOAuth
from GeneralTools import Constents
class Login(APIView):
@classmethod
def get(cls, request):
"""
【功能描述】主要用于示例展示</br>
【返回参数】返回用户请求的网页</br>
"""
code = request.GET.get('code')
state = request.GET.get('state')
# 根据state重新获取WeChatOAuth对象,用此处收到的state和之前的state进一步验证url的可靠性
wechatOAuth = get_WeChatOAuth(Constents.REDIRECT_URI, state)
if code:
access_token = wechatOAuth.fetch_access_token(code)
refresh_token = access_token['refresh_token']
if not wechatOAuth.check_access_token():
# 刷新access_token
wechatOAuth.refresh_access_token(refresh_token)
user_info = wechatOAuth.get_user_info()
print(user_info)
else:
user_info = {}
return render(request, 'login.html', context=user_info)
到了登录页面,就是短信验证,手机注册了。下一节继续腾讯云手机验证。
浙公网安备 33010602011771号