1、前言 vue
一、動態獲取圖片驗證碼ios
二、實現手機驗證碼登陸(工具準備)ajax
三、手機驗證碼登陸(後臺實現)vuex
三、前臺實現express
2、主要內容 json
一、動態獲取圖片驗證碼axios
(1)請求的接口以下,返回的是一張svg的圖片api
## 獲取一次性驗證碼 ### 請求URL: http://localhost:3000/captcha ### 請求方式:
(2)初次顯示圖片,能夠直接在image中的src中請求路徑直接獲得promise
<!--第一次顯示直接請求http://localhost:4000下面的--> <!--點擊圖片的時候要更新圖片,註冊一個點擊事件--> <input type="text" maxlength="11" placeholder="驗證碼" v-model="captche"> <img class="get_verification" src="http://localhost:4000/captcha" alt="captcha" @click='getCaptcha'>
(3)點擊圖片的時候更新,methods中調用方法服務器
//獲取圖片驗證碼 getCaptcha(event){ console.log(this) console.log(event.target) event.target.src="http://localhost:4000/captcha?Time="+Date.now() }
二、實現手機驗證碼登陸(工具準備)
(1)這裏用到「容聯通訊雲」:https://www.yuntongxun.com註冊登陸好以後,每一個人都有不一樣的id號
(2)而後選擇你要的驗證類型
(3)你須要添加一個測試號碼來接收驗證短信
(4)接下來就能夠根據官方文檔寫代碼了
三、手機驗證碼登陸(後臺實現)
(1)後臺項目結構如圖所示
(2)發送shengchen
var md5 = require('blueimp-md5') var moment = require('moment') var Base64 = require('js-base64').Base64; var request = require('request'); /* 生成指定長度的隨機數 */ function randomCode(length) { var chars = ['0','1','2','3','4','5','6','7','8','9']; var result = ""; //統一更名: alt + shift + R for(var i = 0; i < length ; i ++) { var index = Math.ceil(Math.random()*9); result += chars[index]; } return result; } // console.log(randomCode(6)); exports.randomCode = randomCode; /* 向指定號碼發送指定驗證碼 */ function sendCode(phone, code, callback) { var ACCOUNT_SID = '8a216da86a960fd9016a96d0eb580180'; var AUTH_TOKEN = '3abf248c565446d0bf10d46eb62dee07'; var Rest_URL = 'https://app.cloopen.com:8883'; var AppID = '8a216da86a960fd9016a96d0eba80186'; //1. 準備請求url /* 1.使用MD5加密(帳戶Id + 帳戶受權令牌 + 時間戳)。其中帳戶Id和帳戶受權令牌根據url的驗證級別對應主帳戶。 時間戳是當前系統時間,格式"yyyyMMddHHmmss"。時間戳有效時間爲24小時,如:20140416142030 2.SigParameter參數須要大寫,如不能寫成sig=abcdefg而應該寫成sig=ABCDEFG */ var sigParameter = ''; var time = moment().format('YYYYMMDDHHmmss'); sigParameter = md5(ACCOUNT_SID+AUTH_TOKEN+time); var url = Rest_URL+'/2013-12-26/Accounts/'+ACCOUNT_SID+'/SMS/TemplateSMS?sig='+sigParameter; //2. 準備請求體 var body = { to : phone, appId : AppID, templateId : '1', "datas":[code,"1"] } //body = JSON.stringify(body); //3. 準備請求頭 /* 1.使用Base64編碼(帳戶Id + 冒號 + 時間戳)其中帳戶Id根據url的驗證級別對應主帳戶 2.冒號爲英文冒號 3.時間戳是當前系統時間,格式"yyyyMMddHHmmss",需與SigParameter中時間戳相同。 */ var authorization = ACCOUNT_SID + ':' + time; authorization = Base64.encode(authorization); var headers = { 'Accept' :'application/json', 'Content-Type' :'application/json;charset=utf-8', 'Content-Length': JSON.stringify(body).length+'', 'Authorization' : authorization } //4. 發送請求, 並獲得返回的結果, 調用callback // callback(true); request({ method : 'POST', url : url, headers : headers, body : body, json : true }, function (error, response, body) { console.log(error, response, body); callback(body.statusCode==='000000'); // callback(true); }); } exports.sendCode = sendCode; /*調用方式 sendCode('13716**2779', randomCode(6), function (success) { console.log(success); })*/
(2)在index.js中調用
var express = require('express'); var router = express.Router(); const md5 = require('blueimp-md5') const models = require('../db/models') const UserModel = models.getModel('user') const _filter = {'pwd': 0, '__v': 0} // 查詢時過濾掉 const sms_util = require('../util/sms_util') const users = {} const ajax = require('../api/ajax') var svgCaptcha = require('svg-captcha') /* 發送驗證碼短信 */ router.get('/sendcode', function (req, res, next) { //1. 獲取請求參數數據 var phone = req.query.phone; //2. 處理數據 //生成驗證碼(6位隨機數) var code = sms_util.randomCode(6); //發送給指定的手機號 console.log(`向${phone}發送驗證碼短信: ${code}`); sms_util.sendCode(phone, code, function (success) {//success表示是否成功 if (success) { users[phone] = code console.log(users[phone]) console.log('保存驗證碼: ', phone, code) res.send({"code": 0}) } else { //3. 返回響應數據 res.send({"code": 1, msg: '短信驗證碼發送失敗'}) } }) }) /* 短信登錄 */ router.post('/login_sms', function (req, res, next) { var phone = req.body.phone; var code = req.body.code; console.log('/login_sms', phone, code); if (users[code] != code) { res.send({code: 1, msg: '手機號或驗證碼不正確'}); return; } //刪除保存的code delete users[phone]; UserModel.findOne({phone}, function (err, user) { if (user) { req.session.userid = user._id res.send({code: 0, data: user}) } else { //存儲數據 const userModel = new UserModel({phone}) userModel.save(function (err, user) { req.session.userid = user._id res.send({code: 0, data: user}) }) } }) })
三、前臺實現
(1)輸入正確的手機號以後,點擊「獲取驗證碼」,會異步調用getCode()方法
a:頁面行爲
b 調用getCode方法獲取驗證碼
c在methods中定義獲取驗證碼函數
// 異步獲取短信驗證碼 async getCode () { // 若是當前沒有計時 if(!this.computeTime) { // 啓動倒計時 this.computeTime = 60 this.intervalId = setInterval(() => { this.computeTime-- if(this.computeTime<=0) { // 中止計時 clearInterval(this.intervalId) } }, 1000) // 發送ajax請求(向指定手機號發送驗證碼短信) const result = await reqSendCode(this.phone) if(result.code===1) { // 顯示提示 this.showAlert(result.msg) // 中止計時 if(this.computeTime) { this.computeTime = 0 clearInterval(this.intervalId) this.intervalId = undefined } } } },
d.異步請求時會調用本身封裝的請求函數
//6.發送短信驗證碼 export const reqSendCode = (phone)=>ajax('/api/sendcode', {phone})
import axios from 'axios' export default function ajax(url = '', data = {}, type = 'GET') { return new Promise(function (resolve, reject) { let promise if (type === 'GET') { // 準備url query 參數數據 let dataStr = '' //數據拼接字符串 Object.keys(data).forEach(key => { dataStr += key + '=' + data[key] + '&' }) if (dataStr !== '') { dataStr = dataStr.substring(0, dataStr.lastIndexOf('&')) url = url + '?' + dataStr } // 發送get 請求 promise = axios.get(url) } else { // 發送post 請求 promise = axios.post(url, data) } promise.then(response => { resolve(response.data) }) .catch(error => { reject(error) }) }) }
e.後臺接受到get請求,會執行後臺index.js中的get請求方式,先生成驗證碼,而且提示到手機上
router.get('/sendcode', function (req, res, next) { //1. 獲取請求參數數據 var phone = req.query.phone; //2. 處理數據 //生成驗證碼(6位隨機數) var code = sms_util.randomCode(6); //發送給指定的手機號 console.log(`向${phone}發送驗證碼短信: ${code}`); sms_util.sendCode(phone, code, function (success) {//success表示是否成功 if (success) { users[phone] = code console.log(users[phone]) console.log('保存驗證碼: ', phone, code) res.send({"code": 0}) } else { //3. 返回響應數據 res.send({"code": 1, msg: '短信驗證碼發送失敗'}) } }) })
f.用戶收到驗證碼,而且輸入點擊「登陸」按鈕,提交表單,再次對服務器發起post請求,服務器在驗證
router.post('/login_sms', function (req, res, next) { var phone = req.body.phone; var code = req.body.code; console.log('/login_sms', phone, code); if (users[code] != code) { res.send({code: 1, msg: '手機號或驗證碼不正確'}); return; } //刪除保存的code delete users[phone]; UserModel.findOne({phone}, function (err, user) { if (user) { req.session.userid = user._id res.send({code: 0, data: user}) } else { //存儲數據 const userModel = new UserModel({phone}) userModel.save(function (err, user) { req.session.userid = user._id res.send({code: 0, data: user}) }) } }) })
g.前臺接受到後臺的響應數據以後,還須要進行如下操做
1)將電話號碼保存到vuex的state中去
2)進行路由跳轉
if(this.loginWay) { // 短信登錄 const {rightPhone, phone, code} = this if(!this.rightPhone) { // 手機號不正確 this.showAlert('手機號不正確') return } else if(!/^\d{6}$/.test(code)) { // 驗證必須是6位數字 this.showAlert('驗證必須是6位數字') return } // 發送ajax請求短信登錄 result = await reqSmsLogin(phone, code) } // 中止計時 if(this.computeTime) { this.computeTime = 0 clearInterval(this.intervalId) this.intervalId = undefined } // 根據結果數據處理 if(result.code===0) { const user = result.data cosole.log(user) // 將user保存到vuex的state this.$store.dispatch('recordUser', user) // 去我的中心界面 this.$router.replace('/profile') } else { // 顯示新的圖片驗證碼 this.getCaptcha() // 顯示警告提示 const msg = result.msg this.showAlert(msg) } }
3、總結