Web应用微信扫码登录原理与部分功能实现(python)
1.基本原理
-
- 第三方授权
- 能够从可信第三方获取到相应的返回值(用户信息),然后和 user_id 绑定
- 不需要额外再输入密码便完成鉴权过程
- 会创建一组今后可以修改的 user_id 作为 占位用户
- 鉴权成功后设置session状态
- 第三方授权包含:微信、QQ、微博、手机等,这里主要介绍微信。
2.扫二维码登录第三方网站的工作过程
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。其中主要处理的事情如下:
- 向第三方发起鉴权请求
- 第三方鉴权回调
- 和MIS系统本地 user_id 体系关联(新建用户)
- 设置session登录状态
- 处理不同结果的显示界面
用”豆瓣“网站为例
- 打开豆瓣首页,点击微信登录
- 手机端用微信扫二维码登录
上图中二维码等待扫描中,PC浏览器发两个个长链接(比较长时处于 pending 状态)的请求:
- 等待手机端的微信扫码
- 等待手机微信点击 “确认登录” 按钮()
这两个状态都会反馈到PC端的二维码页面,在手机端完成确认后,PC浏览器上面的页面就会生定向到授权后的页面
3.功能实现
class WeChatAuthCallback(MyBaseHandler): """ 微信第三方认证之后,开始将此用户在本系统沉淀下来 - 用于微信服务器传回code的值 - 此处要再请求获得access_token """ async def get(self): wx_code = self.get_argument('code', '') wx_state = self.get_argument('state', '') if wx_code == '': res = ConstData.msg_forbidden dlog.debug(res) self.write(res) return dlog.debug('wx_code:%s,wx_state:%s' % (wx_code, wx_state)) access_token_res = wx_webapp.get_auth_access_token(code=wx_code, state=wx_state) user_info = wx_webapp.get_auth_user_info(auth_access_token_res=access_token_res) """:type:WeChatUser""" # 微信返回的用户信息串 if user_info is None: res = ConstData.msg_forbidden dlog.debug(res) self.write(res) return wechat_user = await MisWeChatUser.objects.get(openid=user_info.openid, unionid=user_info.unionid) """:type:MisWeChatUser""" # 一个Open_id下面所有的id都是靠union来区分账号 if wechat_user is not None: user = await User.objects.get(user_id=wechat_user.user_id) assert user is not None if user.active: if await user.is_online(): await self.update_session() # 更新时间 else: await self.create_session(user) # 新增加一个session self.write('in authorized page') # self.redirect('/') # todo 重定向到登录授权后的主页 return # 如果不存在wechat备案信息,则需要备案wechat信息,而且新注册初始账号 default_new_user_id = 'u_' + get_uuid1_key() new_wechat_user = MisWeChatUser( openid=user_info.openid, nickname=user_info.nickname, unionid=user_info.unionid, # user_id=wx_webapp.appid + '_' + user_info.unionid, # 通过微信号登录生成的一个唯一的用户名,后面可以提供修改 user_id=default_new_user_id, appid=wx_webapp.appid ) new_wechat_user.set_default_rc_tag() # rand_salt = get_rand_salt() new_user = User( user_id=default_new_user_id, # salt=rand_salt, # 防止别人md5撞库反向破解的随机数 # passwd=StringField() # 密码,通过第三方登录的默认不设置 first_name=user_info.nickname, status=FieldDict.user_status_init, # 表示是可更改状态 active=False, ) new_user.set_default_rc_tag() await new_wechat_user.save() await new_user.save() self.write('in unauthorized page') # self.redirect(URL_ROOT) # todo 导入到未授权的页面2019-04-122019-04-122019-04-1215:52:512019-04-

更多精彩