起初的想法是類似於QQ掃碼登錄,BILIBILI掃碼登錄一樣,通過手機確認後,在web端重定向完成登錄
通過對BILIBILI掃碼功能的解析,自己實現了一套類似掃碼登錄的功能
以下爲僞代碼,僅供查閱
前端
需要兩個路由,兩個頁面
login
提供Web端用戶登錄和掃碼
圖片僅提供掃碼展示,密碼登錄不寫了
login2
提供給跨端用戶(如手機端)掃碼進入
主要爲二次確認,提供確認登錄和取消登錄
確認登錄後,頁面跳轉至localhost:3000
後端
功能需求:
-
用戶訪問請求登錄,獲取登錄ID,並存儲其狀態爲false
-
PUT用戶根據登錄ID確認登錄,當狀態爲False是,修改爲TRUE(需要權限驗證)
-
提供當前登錄ID信息查詢
後端實現
- 生成登錄ID,並返回前端
let code = (Math.random() * 100000).toFixed(0);
let data = {
qr_title: code, //登錄ID
qr_status: false, //登錄狀態,未登錄爲False
};
return await this.qrService.create(a);
2.用戶通過二維碼訪問確認登錄頁,確認登錄
@Put('/ConfirmLogin')
async ConfirmLogin(@Query() chaxun: any): Promise<any> {
return await this.qrService.confirm(chaxun);
}
async confirm(dto?: any): Promise<any> {
try {
let data: Array<any> = await this.qrRepository.find({
qr_title: dto.qr,
});
if (data.length > 0 && !data[0].qr_status) {
data[0].qr_status = true;
this.qrRepository.save(data[0]);
} else {
}
} catch (error) {
throw new BadRequestException(`系統錯誤`);
}
}
- 輪詢請求狀態
@Get('/login')
async login(@Query() chaxun: any): Promise<any> {
console.log(chaxun);
return await this.qrService.login(chaxun);
}
async login(dto?: any): Promise<any> {
try {
let data: Array<any> = await this.qrRepository.find({
qr_title: dto.qr,
});
if (data[0].qr_status) {
return { loginStatus: 'OK' };
} else {
return { loginStatus: 'NOOK' };
}
} catch (error) {
throw new BadRequestException(`系統錯誤`);
}
}
前端實現
引入QrCode庫,根據請求的登錄ID生成二維碼,將參數帶入手機確認登錄頁
同時該頁面輪詢登錄狀態,登錄成功後,跳轉至網站內容頁
Login1
import React, { Component } from 'react';
import axios from '../utils/http';
import { message } from 'antd';
var QRCode = require('qrcode.react');
export default class LoginRouter extends Component {
code: number = 0;
number: number = 0;
hello: any = null;
render() {
console.log(this.code);
console.log(this.props);
return (
<div>
<QRCode value={`http://192.168.1.125:3000/login2?qr=${this.code}`} />,
</div>
);
}
tick = async() => {
this.number += 1;
const res = await axios.get<{ loginStatus:string }>(
`http://localhost:4000/qr/login?qr=${this.code}`
);
console.log(res.data);
if (res.data.loginStatus==='OK') {
let a: any = this.props;
message.success('登陸成功');
a.history.push('/');
}
};
componentDidMount() {
axios.get('http://192.168.1.125:4000/qr').then(res => {
this.code = res.data.code;
this.setState({});
});
this.hello = setInterval(this.tick, 1000);
}
componentDidUpdate() {
// 組件更新後觸發
console.log('componentDidUpdate');
}
componentWillUnmount() {
// 組件卸載時觸發
clearInterval(this.hello);
console.log('componentWillUnmount');
}
}
Login2
手機登錄頁面確認後,提交確認狀態,交給主登錄頁輪詢狀態
import React, { Component } from 'react';
import axios from '../utils/http';
import { message } from 'antd';
export default class LoginRouter2 extends Component {
code: number = 0;
render() {
let a: any = this.props;
let qr = a.history.location.search.split('=')[1];
return (
<div>
<button
onClick={() => {
axios
.put(`http://192.168.1.125:4000/qr/ConfirmLogin?qr=${qr}`)
.then(res => {
message.success('成功');
});
}}
>
確認
</button>
<button
onClick={() => {
alert('請關閉');
}}
>
取消
</button>
</div>
);
}
componentDidMount() {
// axios.get('http://192.168.1.125:4000/qr').then(res => {
// this.code = res.data.code;
// this.setState({});
// });
}
}
只是理論可行,實際應用還需要判斷其權限,手機端授權,頁面端登錄權限驗證等,以及前端頁面的掃碼狀態展示,掃碼回執操作等
當然二維碼也未必是指向本文章中的login2
如手機端可通過自定義協議訪問,比如支付寶或微信付款嗎alipay://
GIF示例-PC
GIF示例-Mobile
表
文章來源:JoyNop.COM–跨端掃碼確認實現Web登錄(掃二維碼登錄)
https://www.joynop.com/p/235.html