前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
文章目录
- ⭐前言
- ⭐qq三方登录流程
- 💖qq互联中心创建网页应用
- 💖配置回调地址redirect_uri
- 💖流程分析
- ⭐思路分解
- ⭐技术选型+实现
- 💖技术选型:
- 💖实现
- ⭐结束
⭐前言
大家好,我是yma16,本文分享OAuth规则机制下实现个人站点接入qq三方登录。
oauth授权
OAuth是一种授权机制,用于允许用户(资源所有者)向第三方应用程序授予有限的访问权限,而不必将凭证直接提供给第三方应用程序。OAuth的目的是为了保护用户的私密数据,如社交媒体帐户、云存储、银行帐户等。它通过一个流程,将用户授权给第三方应用程序访问用户的资源,而不需要第三方应用程序获得用户的凭证信息。这样做可以减少用户数据泄露的风险。OAuth是一个开放的标准,由OAuth工作组维护,并得到许多组织的支持和使用。
oauth的发展
OAuth协议的发展历史可以追溯到2004年,当时美国国防部提出了一个名为“OpenID Connect”的开放式身份认证和授权标准,旨在解决Web 2.0中的身份认证和授权问题。OAuth1.0于2005年被RFC 5849正式标准化,OAuth2.0于2011年被RFC 6749正式标准化 。
OAuth1.0的主要特点是将用户的认证信息(如用户名和密码)与第三方应用的请求分离开来,从而提高了安全性。
OAuth2.0则在OAuth1.0基础上进一步改进,增加了更多的功能和灵活性,如授权码模式、隐式模式、密码模式等 。
效果
在个人站点实现三方qq登录
链接直达:https://yongma16.xyz
唤起三方登录url
获取qq用户账号头像和openid登入

⭐qq三方登录流程
前提条件: 存在可访问的网站,在qq互联中心创建应用审核
友情提示:网站不可使用外部cdn,可导致审核人员查看白屏而失败
💖qq互联中心创建网页应用
填写域名资料,提交审核

💖配置回调地址redirect_uri
回调地址是用户使用qq登录之后调整的地址会携带code和state的参数
💖流程分析
- 唤起qq授权登录url
- 登录qq成功获取code
- 通过code去换取access_token
- 通过access_token去换取openid
- 通过access_token和openid去换取userinfo

⭐思路分解
1.登录页面新开窗口的auth授权qq页面
2.自定义node服务去渲染回调redirect_uri,成功登录时回传url上的参数给父页面,然后用定时器关闭页面
3. 拿到code后去换取token
4. 拿到token去换取openid
5. 拿到openid去换取userinfo
6. 使用openid去注册网站用户,显示nickname网名
⭐技术选型+实现
💖技术选型:
后端:
node
前端:
vue2
后端node封装接口
💖实现
node封装接口:
api.js
const request = require('request');const loginUrl='https://graph.qq.com/oauth2.0/authorize'
const codeToTokenUrl='https://graph.qq.com/oauth2.0/token'
const openIdUrl='https://graph.qq.com/oauth2.0/me'
const userInfoUrl='https://graph.qq.com/user/get_user_info'
const appid=自己的appid
const appKey=自己的appkey
const redirect_uri=自己的回调地址const getAuthUrl=(state)=>{return new Promise(resolve=>{const params={response_type:'code',client_id:appid,redirect_uri:encodeURI(redirect_uri),state:state?state:'myblog',};const path=Object.keys(params).forEach(key=>{return `${key}=${params[key]}`}).join('&')const url=loginUrl+'?'+pathresolve(url)})
};const getToken=(code)=>{return new Promise(async ( resolve ,reject)=> {request({method: 'GET', uri: codeToTokenUrl,qs: {grant_type: 'authorization_code',client_id: appid,client_secret: appKey,code: code,redirect_uri: encodeURI(redirect_uri),fmt: 'json'}}, function (error, response) {if (!error && response.statusCode === 200) {resolve(response)} else {console.log("error",error);reject(reject)}})})
};const getOpenId=(access_token)=>{return new Promise(async ( resolve ,reject)=> {request({method: 'GET', uri: openIdUrl,qs: {access_token:access_token,fmt: 'json'}}, function (error, response) {if (!error && response.statusCode === 200) {resolve(response)} else {reject(error)}})})
};const getUserInfo=(access_token,openId)=>{return new Promise(async ( resolve ,reject)=> {request({method: 'GET', uri: userInfoUrl,qs: {access_token:access_token,oauth_consumer_key:appid,openid:openId,fmt: 'json'}}, function (error, response) {if (!error && response.statusCode === 200) {resolve(response)} else {reject(error)}})})
}module.exports={getAuthUrl,getToken,getOpenId,getUserInfo
};
node开放接口:
const hostname = 'localhost';
const port = 6677;const express = require("express");const {getAuthUrl,getToken,getOpenId,getUserInfo}=require('./service/api.js');
const app = express();app.listen(port,hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
// server your css as static
app.use(express.static(__dirname));
// views
const thirdLoginDir='/views/thirdLogin/';
app.get("/getAuthUrl",async (req, res) => {try{const {query}=reqconst {state}=queryconst url=await getAuthUrl(state)res.json({code:authRes.statusCode,data:url,})}catch (e) {res.json({code:0,msg:e})}
});app.get("/getToken",async (req, res) => {try{const {query}=reqconst {code}=queryconsole.log('code',code)const tokenRsponse=await getToken(code)res.json({code:tokenRsponse.statusCode,data:JSON.parse(tokenRsponse.body),})}catch (e) {res.json({code:0,msg:e})}
});app.get("/getOpenId",async (req, res) => {try{const {query}=reqconst {access_token}=queryconsole.log('access_token',access_token)const openidRes=await getOpenId(access_token)res.json({code:openidRes.statusCode,data:JSON.parse(openidRes.body)})}catch (e) {res.json({code:0,msg:e})}
});app.get("/quickGetOpenId",async (req, res) => {try{const {query}=reqconst {code}=queryconsole.log('code',code)const tokenRsponse=await getToken(code)const tokenBody=JSON.parse(tokenRsponse.body)const {access_token}=tokenBodyconst openIdRsponse=await getOpenId(access_token)res.json({code:tokenRsponse.statusCode,data:JSON.parse(openIdRsponse.body)})}catch (e) {res.json({code:0,msg:e})}
});app.get("/getUserInfo",async (req, res) => {try{const {query}=reqconst {access_token,openId}=queryconsole.log('access_token openId',access_token,openId)const userInfoRes=await getUserInfo(access_token,openId)res.json({code:userInfoRes.statusCode,data:JSON.parse(userInfoRes.body)})}catch (e) {res.json({code:0,msg:e})}
});app.get("/qq_login_callback", (req, res) => {res.sendFile(__dirname + thirdLoginDir+"qqLoginCallback.html");
});
app.get("/azure_login_callback", (req, res) => {res.sendFile(__dirname + thirdLoginDir+"azureLoginCallback.html");
});
回调html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>qqLoginCallback</title>
</head>
<body>
qq login success!
<script type="application/javascript">function init() {console.log('qq success login')console.log('window.location.href',window.location.href)const href=window.location.hrefconst data={}const urlArray=href.split('?')const urlLength=urlArray.lengthif(urlLength>1){urlArray[urlLength-1].split('&').forEach(item=>{const itemArray=item.split('=')const key=itemArray[0]const value=itemArray[1]data[key]=value})}if(window.opener){//发送datawindow.opener.postMessage(data,'*')//关闭setTimeout(()=>{window.close()},1000)}}window.onload=init
</script>
</body>
</html>
vue前端qq登录的调用:
async qqLogin () {try {const that = this// qqconst res = await that.$axios.post('/third-login/getAuthUrl')console.log('res', res)if (res.data && res.data.data) {const resData = res.data.dataconsole.log('resData', resData)if (resData ) {let url = resData console.log('url', url)const openHandle = window.open(url, 'width:800px;height:700px', '_black')console.log('openHandle', openHandle)window.onmessage = async (res) => {const {origin, data} = resif (origin.includes('yongma16.xyz')) {const {code, state} = dataconsole.log('code state', code, state)that.thirdLoginConfig.qCode = codethat.thirdLoginConfig.qState = stateconst tokenRes = await that.getAccessToken(code)console.log('tokenRes', tokenRes)}}}}return new Promise(resolve => {resolve(true)})} catch (e) {return new Promise((resolve, reject) => {reject(e)})}},async getAccessToken (code) {try {const tokenUrl = '/third-login/getToken'const params = {code}const tokenRes = await this.$axios.get(tokenUrl, {params})console.log('tokenRes', tokenRes)if (tokenRes) {const {access_token, expires_in, refresh_token} = tokenRes.data.dataif (access_token) {this.thirdLoginConfig.qToken = access_tokenawait this.getOpenId(access_token)}}} catch (e) {console.log('token error', e)}},async getOpenId (token) {try {const tokenUrl = '/third-login/getOpenId'const params = {access_token: token}const openIdRes = await this.$axios.get(tokenUrl, {params})console.log('openIdRes', openIdRes)if (openIdRes) {const {openid} = openIdRes.data.dataif (openid) {this.thirdLoginConfig.qOpenid = openidawait this.getQUserinfo(this.thirdLoginConfig.qToken, openid)}}} catch (e) {console.log('token error', e)}},async getQUserinfo (token, openId) {try {const userInfoUrl = '/third-login/getUserInfo'const params = {access_token: token,openId: openId}const userRes = await this.$axios.get(userInfoUrl, {params})if (userRes) {this.thirdLoginConfig.qUserInfo = userRes.data.datathis.registerThirdLogin()}console.log('userRes', userRes)} catch (e) {console.log('token error', e)}}
效果:

⭐结束
本文分享到这结束,如有错误或者不足之处欢迎指出!

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!
相关文章:
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
文章目录 ⭐前言⭐qq三方登录流程💖qq互联中心创建网页应用💖配置回调地址redirect_uri💖流程分析 ⭐思路分解⭐技术选型实现💖技术选型:💖实现 ⭐结束 ⭐前言 大家好,我是yma16,本…...
huggingface新作品:快速和简便的训练模型
AutoTrain Advanced是一个用于训练和部署最先进的机器学习模型的工具。它旨在提供更快速、更简便的方式来进行模型训练和部署。 安装 您可以通过PIP安装AutoTrain-Advanced的Python包。请注意,为了使AutoTrain Advanced正常工作,您将需要python > 3.…...
利用鸿鹄优化共享储能的SCADA 系统功能,赋能用户数据自助分析
摘要 本文主要介绍了共享储能的 SCADA 系统大数据架构,以及如何利用鸿鹄来更好的优化 SCADA 系统功能,如何为用户进行数据自助分析赋能。 1、共享储能介绍 说到共享储能,可能不少朋友比较陌生,下面我们简单介绍一下共享储能的价值…...
noSQL语句练习
Redis练习题 string list hash结构中,每个至少完成5个命令,包含插入 修改 删除 查询,list 和hash还需要增加遍历的操作命令 1、 string类型数据的命令操作: (1) 设置键值: 127.0.0.1:63…...
Spring:Bean生命周期
Bean 生命周期生命周期 Bean 生命周期是 bean 对象从创建到销毁的整个过程。 简单的 Bean 生命周期的过程: 1.实例化(调用构造方法对 bean 进行实例化) 2.依赖注入(调用 set 方法对 bean 进行赋值) 3.初始化(手动配置 xml 文件中 bean 标签的 init-method 属性值,来指…...
Vue自定义指令
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。 自定义指令函数式v-big: &l…...
SpringBoot+JWT实现单点登录解决方案
一、什么是单点登录? 单点登录是一种统一认证和授权机制,指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的系统,不需要重新登录验证。 单点登录一般用于互相授信的系统,实现单一位置登录,其他信任的…...
中国国债发行数据集(2002-2023)
国债是由国家发行的债券,由于国债的发行主体是国家,所以它具有最高的信用度,被公认为是最安全的投资工具。国债按照交易市场的不同分为三类,即银行间市场国债、交易所市场国债和柜台市场国债;按照交易方式的不同分为三…...
曲师大2023大一新生排位赛-C.String题解
C.String 题目描述 众所周知,许师哥精通字符串。 一天,许师哥意外的获得了一个字符串,但他发现这个字符串并不是一个回文串,因此他非常生气。于是他决定从这个字符串中删除若干个字符使得 剩余的字符串为一个回文串。 回想回文串…...
Linux Ubuntu安装RabbitMQ服务
文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…...
什么是测试用例?如何设计?
在学习或者实际的测试工作中经常都会提到“测试用例”这个词,没错,测试用例是测试工作的核心,不管要做的是什么样的测试,在真正动手执行测试之前,我们都需要先根据软件需求来设计测试用例,之后再依据设计好…...
Maven —— 项目管理工具
前言 在这篇文章中,荔枝会介绍如何在项目工程中借助Maven的力量来开发,主要涉及Maven的下载安装、环境变量的配置、IDEA中的Maven的路径配置和信息修改以及通过Maven来快速构建项目。希望能对需要配置的小伙伴们有帮助哈哈哈哈~~~ 文章目录 前言 一、初…...
Ubuntu 命令行编辑文件后如何保存退出
在 Ubuntu 命令行中编辑文件后,可以使用以下步骤保存并退出: 按下键盘上的 Ctrl 键和 X 键组合,以退出编辑模式。如果文件已更改,你将看到提示,询问是否保存更改。按下 Y 键来确认保存更改,或按下 N 键取消…...
AHB协议理解
从小父亲就教育我,做一个对社会有用的人! 目录 Chapter1 AHB Block Diagram Ginput signal lnput signals Output Signal Chapter3 Transfers AHB接口Overview Chapter6 Data Buses HWDATA HRDATA Chapter1 Introduction AHB: Advanced High-performanc…...
【UE5 多人联机教程】01-创建主界面
目录 工程地址 步骤 参考链接 工程地址 GitHub - UE4-Maple/C_MP_Lobby: 多人大厅教程项目 步骤 1. 先新建一个工程 2. 将下载的工程中的Plugins目录拷贝到自己新建的工程下 3. 打开工程,新建一个游戏实例 这里命名为“GI_Main” 在项目设置中设置游戏实例类为…...
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 五)
Styles装饰器:定义组件重用样式 如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器St…...
React(3)
1.案例选项卡 import React, { Component } from reactexport default class App extends Component {state{tabList:[{id:1,text:"电影"},{id:2,text:"影院"},{id:3,text:"我的"}]}render() {return (<div><ul>{this.state.tabList…...
LangChain大型语言模型(LLM)应用开发(三):Chains
LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互&#x…...
FPGA——点亮led灯
文章目录 一、实验环境二、实验任务三、实验过程3.1 编写verliog程序3.2 引脚配置 四、仿真4.1 仿真代码4.2仿真结果 五、实验结果六、总结 一、实验环境 quartus18.1 vscode Cyclone IV开发板 二、实验任务 每间隔1S实现led灯的亮灭,实现流水灯的效果。 三、实…...
idea创建spark教程
1、环境准备 java -version scala -version mvn -version spark -version 2、创建spark项目 创建spark项目,有两种方式;一种是本地搭建hadoop和spark环境,另一种是下载maven依赖;最后在idea中进行配置,下面分别记录两…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
