微信公衆號網頁受權及帳戶綁定

功能介紹

  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等用戶信息數據暴露,致使安全風險

相關文章
相關標籤/搜索