前端笔记_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中进行配置,下面分别记录两…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
