微信公众号网页受权及帐户绑定

功能介绍

  1. 微信公众号受权
  2. 绑定帐号
  3. 自动登陆

流程图

微信公众号受权登陆

原理:

当用户打开某页面(如:/goodslist),咱们须要获取用户信息或实现用户自动登陆,让用户进行微信受权。html

使页面跳转到微信给定的受权页面(https://open.weixin.qq.com/connect/oauth2/authorize?{一些传参}#wechat_redirect)前端

该受权页会提示用户受权,这样用户是否受权,微信可以感知到。react

受权成功后,跳回咱们在{一些参数}中指定的redirect_uri重定向页面,通常设为跳转以前的页面(/goodslist)ios

微信会在重定向uri后面添加参数code,如:/goodslist?code=xxxxxx(还有一个参数state)web

在跳回的页面拿到code去跟微信换取用户信息(第一步,使用code换取access_token;第二步,拉取用户信息)redux

使用code换取用户信息由咱们本身的服务端去请求,前端就不用管了,由于须要提交一些安全性参数后端

一些参数:(微信要求,这些参数的顺序不能改变)

  1. appid - 公众号的惟一标识
  2. redirect_uri - 受权后重定向的回调连接地址,请使用 urlEncode 对连接进行处理
  3. response_type - 返回类型,固定值code
  4. scope - 应用受权做用域,见下方
  5. state - 重定向后会带上state参数,开发者能够填写a-zA-Z0-9的参数值,最多128字节

scope

应用受权做用域,可选值:snsapi_base, snsapi_userinfoapi

  1. snsapi_base浏览器

    不弹出受权页面,直接跳转,只能获取用户openid安全

  2. snsapi_userinfo

    弹出受权页面,可经过openid拿到昵称、性别、所在地。而且, 即便在未关注的状况下,只要用户受权,也能获取其信息

参考手册

网页受权

代码实现

判断浏览器环境

// src/utils/env.js
// 使用bowser库
import Bowser from 'bowser'

const parsed = Bowser.getParser(window.navigator.userAgent).parsedResult

// 是否微信环境
export const inWechat = parsed.browser.name === 'WeChat'

export const inIOS = parsed.os.name === 'iOS'

export const inSafari = parsed.browser.name === 'Safari'
复制代码

微信受权

// src/auth.js

import qs from 'qs'

// store2库 方便操做localStorage 和 sessionStorage
import store from 'store2'

import { inWechat } from '@/utils/env'

import { getUserInfo } from '@/service/login'

// 微信appid
const appid = 'wxxxxxxxxxxxxx'

// 前往受权
const goAuth = () => {
  const uri = 'https://open.winxin.qq.com/connect/oauth2/authorize'
  
  const params = {
    appid,
    redirect_uri: window.location.href,
    response_type: 'code',
    scope: 'snsapi_userinfo',
    state: 'STATE'
  }
  
  const hash = 'wechat_redirect'
  
  const url = `${url}?${qs.stringify(params)}#${hash}`

  // 页面跳转,ios等机型禁止了直接使用location.href跳转
  // window.location.href = url // 不能使用

  const nextPage = document.createElement('a')
  nextPage.setAttribute('href', url)
  nextPage.click()

  // 这里为了得到更友好的效果,能够提示用户须要受权,给出一个前往受权的按钮。用户点击后触发
}

/** 受权返回 * code - 受权后redirect_uri后面参数中的code * callback - 这里通常指定为dom渲染的操做 */
const authBack = async (code, callback) => {
  // 使用code请求用户信息
  await getUserInfo(code)
  
  callback()
}

export default async callback => {
  if (
    window.location.pathname === '/login' // 登陆绑定页
    || store('token') // 已登陆
    || !inWechat // 非微信环境下
  ) {
    // 直接渲染dom
    return callback() 
  }

  // 解析querystring
  const params = qs.parse(window.location.search, { ignoreQueryPrefix: true })
  params.code === undefined ? goAuth() : await authBack(params.code, callback)
}
复制代码
// src/index.js

import React from 'react'
import ReactDOM from 'react-dom'

import auth from './auth'

import { Provider } from 'react-redux'
import store from './store'
import Router from './router'

const renderDom = () => ReactDOM.render(
  <Provider store={store}> <Router /> </Provider>,
  document.getElementById('root')
)

// 受权完成后,才能继续页面渲染,这样能够阻止页面中发出的请求。
// 尤为是这些请求中有的是要求必须登陆的,将致使页面跳转到登陆页
auth(renderDom)

复制代码

后记,一些思考

另外一种受权流程

redirect_uri 设置为一个后端地址(前端路由不能匹配到的地址,如:/auth);

state 设置为前端回跳地址, 如:window.location.href

用户受权成功后,微信跳转到后端地址并带上code和state参数(/auth?code={code}&state={前端地址})

后端(/auth)获取到code以后,跟微信交换用户信息。若是该微信用户已注册,则进行登陆操做,返回token,将页面重定向到{前端地址}?token={token}&openid={openid}&{其余用户信息};该用户未注册,则重定向到{登陆页面}?openid={openid}

优势

能够简化前端流程

不足

后端重定向前端页面,会将token等用户信息数据暴露,致使安全风险

相关文章
相关标签/搜索