QQ登录的具体流程
文章目录
- 网站授权QQ登录
- QQ登录的完整流程
- 代码示例
- 1. 添加依赖
- 2. 配置文件
- 3. 实现Service
- 4. 创建Controller
网站授权QQ登录
- 首先需要去QQ互联申请应用
- 填写网站的相关信息,以及回调地址,需要进行审核。
- 申请流程暂时不说了,百度一下挺多申请失败案例的解决方案的,你懂的现在越来越严格了,甚至一个错别字都不让有。
QQ登录的完整流程
-
用户点击QQ登录
用户在你的前端页面点击QQ登录按钮,发送请求到后端。 -
重定向到QQ授权页面
后端也可以直接重定向到QQ的授权页面
,也可以将授权页面的地址返回给前端, 由前端将用户重定向到QQ的授权页面,授权页面的地址通常是一个URL,类似于:https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=YOUR_APP_ID&redirect_uri=YOUR_REDIRECT_URI&state=YOUR_STATE
其中:
YOUR_APP_ID
:你在QQ开放平台注册应用时获得的APP ID。YOUR_REDIRECT_URI
:你在QQ开放平台设置的回调URL。YOUR_STATE
:一个随机字符串,用于防止CSRF攻击。
-
用户授权
用户在QQ的授权页面点击同意授权。 -
QQ重定向到回调URL
授权成功后,QQ会将用户重定向到你设置的redirectUri
,并在回调地址的查询参数中加上一个code
参数和原先的state
。 -
前端获取
code
并验证state
前端从回调地址中解析出code
参数。同时,验证返回的state
是否与最初发送的state
一致,以确保这不是一个CSRF攻击。
state参数也可以交给后端进行验证
这里的回调地址就是QQ互联上面写的回调地址,前端会在这个回调地址的页面发送请求给后端,同时携带code和state参数(这两个参数从回调地址里面取出来的)
-
前端向后端发送登录请求并携带code和state参数
前端发起请求,将code和state
发送到后端的/callback
接口。 -
后端获取Access Token
后端使用code
,向QQ服务器请求访问令牌(Access Token)。这通常涉及到一个POST请求到https://graph.qq.com/oauth2.0/token
,带有code
、YOUR_APP_ID
、YOUR_APP_KEY
(你的应用密钥)和YOUR_REDIRECT_URI
作为参数。 -
后端获取OpenID
使用Access Token,后端可以向QQ服务器请求OpenID,这是一个代表QQ用户唯一标识的值。 -
后端获取用户信息
后端使用Access Token和OpenID,请求QQ服务器以获取用户的基本信息。 -
创建或登录用户
后端可以使用从QQ获取的用户信息来:- 检查数据库中是否已经有一个与此QQ账户关联的用户。
- 如果是,则登录该用户。
- 如果不是,则创建一个新用户,并与该QQ账户关联。
-
返回结果到前端
后端可以返回一个令牌(如JWT)或其他标识已登录用户的信息到前端。 -
前端处理登录状态
前端根据后端的响应处理用户的登录状态,例如保存JWT,显示用户的信息等。
代码示例
1. 添加依赖
在pom.xml
中添加相关的依赖:
<!-- Spring Boot Web Starter: 提供了创建web应用所需要的所有必要依赖,包括内嵌的Tomcat服务器 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- Apache HttpClient: 一个流行的库,用于处理HTTP请求 -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId>
</dependency><!-- Jackson Databind: 用于将Java对象与JSON数据进行序列化和反序列化 -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency>
2. 配置文件
在application.properties
添加:
qq.appId=YOUR_APP_ID
qq.appKey=YOUR_APP_KEY
qq.redirectUri=http://yourdomain.com/auth/qq/callback
3. 实现Service
创建一个QQAuthService
用于处理与QQ的交互。
@Service
public class QQAuthService {// 从application.properties中读取配置值@Value("${qq.appId}")private String appId;@Value("${qq.appKey}")private String appKey;@Value("${qq.redirectUri}")private String redirectUri;// 创建一个可关闭的HTTP客户端,用于发送请求private final CloseableHttpClient httpClient = HttpClients.createDefault();/*** 获取Access Token* * @param code 从QQ回调URL中获得的授权码* @return 返回Access Token* @throws IOException 处理HTTP请求可能会出现的IO异常*/public String getAccessToken(String code) throws IOException {// 构建获取Access Token的URLString url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=" + appId + "&client_secret=" + appKey + "&code=" + code + "&redirect_uri=" + redirectUri;// 创建一个HttpGet请求HttpGet httpGet = new HttpGet(url);// 执行该请求,并获取响应CloseableHttpResponse response = httpClient.execute(httpGet);// 将响应内容转换为字符串String responseStr = EntityUtils.toString(response.getEntity());// 解析响应内容,提取access_tokenString accessToken = responseStr.split("&")[0].split("=")[1];return accessToken;}/*** 获取OpenID* * @param accessToken Access Token* @return 返回OpenID* @throws IOException 处理HTTP请求可能会出现的IO异常*/public String getOpenId(String accessToken) throws IOException {// 构建获取OpenID的URLString url = "https://graph.qq.com/oauth2.0/me?access_token=" + accessToken;// 创建一个HttpGet请求HttpGet httpGet = new HttpGet(url);// 执行该请求,并获取响应CloseableHttpResponse response = httpClient.execute(httpGet);// 将响应内容转换为字符串String responseStr = EntityUtils.toString(response.getEntity());// 解析响应内容,提取openidString openId = responseStr.substring(responseStr.lastIndexOf(":\"") + 2, responseStr.lastIndexOf("\"}"));return openId;}/*** 获取用户信息* * @param accessToken Access Token* @param openId OpenID* @return 返回用户信息的JSON字符串* @throws IOException 处理HTTP请求可能会出现的IO异常*/public String getUserInfo(String accessToken, String openId) throws IOException {// 构建获取用户信息的URLString url = "https://graph.qq.com/user/get_user_info?access_token=" + accessToken + "&oauth_consumer_key=" + appId + "&openid=" + openId;// 创建一个HttpGet请求HttpGet httpGet = new HttpGet(url);// 执行该请求,并获取响应CloseableHttpResponse response = httpClient.execute(httpGet);// 将响应内容转换为字符串String responseStr = EntityUtils.toString(response.getEntity());// 直接返回用户信息的JSON字符串return responseStr; }
}
4. 创建Controller
@RestController
@RequestMapping("/auth/qq")
public class QQAuthController {@Autowiredprivate QQAuthService qqAuthService;/*** 重定向用户到QQ登录页面。* * @param response HttpServletResponse对象,用于发送重定向。* @param session HttpSession对象,用于存储state。* @throws IOException 如果重定向失败。*/@GetMapping("/login")public void qqLogin(HttpServletResponse response, HttpSession session) throws IOException {// 生成并存储一个唯一的state值String state = UUID.randomUUID().toString();session.setAttribute("qq_oauth_state", state);// 构建QQ授权的URLString url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=" + appId + "&redirect_uri=" + URLEncoder.encode(redirectUri, "UTF-8") + "&state=" + state;// 当你在移动端上请求登录时,可以在请求中带上display=mobile参数// 系统就会跳转到移动版的QQ登录页面,为用户提供更好的体验if ("mobile".equals(display)) {url += "&display=mobile";}// 重定向到QQ授权页面response.sendRedirect(url);}/*** 处理QQ授权的回调请求。* * @param code QQ授权返回的code。* @param state QQ授权返回的state。* @param session HttpSession对象,用于验证state。* @return 用户信息或错误消息。*/@GetMapping("/callback")public String qqCallback(@RequestParam String code, @RequestParam String state, HttpSession session) {// 检查返回的state是否与存储的一致String storedState = (String) session.getAttribute("qq_oauth_state");if (storedState == null || !storedState.equals(state)) {return "Error: state does not match";}try {// 获取并使用AccessToken和OpenIDString accessToken = qqAuthService.getAccessToken(code);String openId = qqAuthService.getOpenId(accessToken);String userInfo = qqAuthService.getUserInfo(accessToken, openId);// 这里可以进行用户注册或登录操作// 这里可以根据用户是新用户还是老用户决定是注册后登录还是直接登录// 然后返回登录用户的信息return userInfo;} catch (IOException e) {return "Error occurred during QQ auth: " + e.getMessage();}}
}
相关文章:
QQ登录的具体流程
文章目录 网站授权QQ登录QQ登录的完整流程代码示例1. 添加依赖2. 配置文件3. 实现Service4. 创建Controller 网站授权QQ登录 首先需要去QQ互联申请应用填写网站的相关信息,以及回调地址,需要进行审核。申请流程暂时不说了,百度一下挺多申请失…...
用JMeter对HTTP接口进行压测(一)压测脚本的书写、调试思路
文章目录 安装JMeter和Groovy为什么选择Groovy? 压测需求以及思路准备JMeter脚本以及脚本正确性验证使用Test Script Recorder来获取整条业务线上涉及的接口为什么使用Test Script Recorder? 配置Test Script Recorder对接口进行动态化处理处理全局变量以…...
接着聊聊如何从binlog文件恢复误delete的数据,模拟Oracle的闪回功能
看腻了文章就来听听视频演示吧:https://www.bilibili.com/video/BV1cV411A7iU/ delete忘加where条件(模拟Oracle闪回) 操作基本等同于上篇:再来谈谈如何从binlog文件恢复误update的数据,模拟Oracle的回滚功能 原理&a…...
计算机竞赛 深度学习机器视觉车道线识别与检测 -自动驾驶
文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 🔥 优质竞赛项目系列,今天要分…...
pyqt5使用经验总结
pyqt5环境配置注意: 安装pyqt5 pip install PyQt5 pyqt5-tools 环境变量-创建变量名: 健名:QT_QPA_PLATFORM_PLUGIN_PATH 值为:Lib\site-packages\PyQt5\Qt\plugins pyqt5经验2: 使用designer.exe进行设计࿱…...
【MQTT】mosquitto库中SSL/TLS相关API接口
文章目录 1.相关API1.1 mosquitto_tls_set1.2 mosquitto_tls_insecure_set1.3 mosquitto_tls_opts_set1.4 mosquitto_tls_insecure_set1.5 mosquitto_tls_set_context1.6 mosquitto_tls_psk_set 2.示例代码 Mosquitto 是一个流行的 MQTT 消息代理(broker)…...
假期题目整合
1. 下载解压题目查看即可 典型的猪圈密码只需要照着输入字符解开即可得到答案 2. 冷门类型的密码题型,需要特意去找相应的解题思路,直接百度搜索天干地支解密即可 3. 一眼能出思路他已经给了篱笆墙的提示提示你是栅栏密码对应解密即可 4. 最简单的社会主…...
Redisson—分布式服务
一、 分布式远程服务(Remote Service) 基于Redis的Java分布式远程服务,可以用来通过共享接口执行存在于另一个Redisson实例里的对象方法。换句话说就是通过Redis实现了Java的远程过程调用(RPC)。分布式远程服务基于可…...
volatile使用方法
volatile使用方法 编译优化。使用等级3的话,可能将优化了一些变量。 这为什么会开启等第三呢?这是关于单片机的内存容量比较小,所以开启优化的话,可以可以省一些空间,但是如果。会出现些变量的问题,需要通过…...
提升您的 Go 应用性能的 6 种方法
优化您的 Go 应用程序 1. 如果您的应用程序在 Kubernetes 中运行,请自动设置 GOMAXPROCS 以匹配 Linux 容器的 CPU 配额 Go 调度器 可以具有与运行设备的核心数量一样多的线程。由于我们的应用程序在 Kubernetes 环境中的节点上运行,当我们的 Go 应用程…...
计算摄像技术02 - 颜色空间
一些计算摄像技术知识内容的整理:颜色视觉与感知特性、颜色空间和基于彩色滤镜阵列的彩色感知。 文章目录 一、颜色视觉与感知特性 (1)色调 (2)饱和度 (3)明度 二、颜色空间 (1&…...
Pytorch笔记之分类
文章目录 前言一、导入库二、数据处理三、构建模型四、迭代训练五、模型评估总结 前言 使用Pytorch进行MNIST分类,使用TensorDataset与DataLoader封装、加载本地数据集。 一、导入库 import numpy as np import torch from torch import nn, optim from torch.uti…...
【目标检测】——PE-YOLO精读
yolo,暗光目标检测 论文:PE-YOLO 1. 简介 卷积神经网络(CNNs)在近年来如何推动了物体检测的发展。许多检测器已经被提出,而且在许多基准数据集上的性能正在不断提高。然而,大多数现有的检测器都是在正常条…...
Java 数组转集合
数组转集合 如果仅仅这样转化Arrays.asList(数组),导致集合只能查询,无法进行其他操作,因此,对该方法进行优化: List<实体> list1 new ArrayList<>(Arrays.asList(数组))以上方法就可以使用集合的所有操…...
Elasticsearch:ES|QL 查询语言简介
警告:此功能处于技术预览阶段,可能会在未来版本中更改或删除。 Elastic 将尽最大努力解决任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。在目前的 Elastic Stack 8.10 中此功能还没有提供。 Elasticsearch 查询语言 (ES|…...
qt qml中listview出现卡顿情况时的常用处理方法
如果在qt QML中使用ListView时出现卡顿情况,可能是因为渲染大量的数据或者在模型中进行复杂的数据处理。以下是常用的解决方法: 1. 设置ListView的缓存策略:通过设置ListView的cacheBuffer属性为适当的值,可以提高滚动的流畅性。…...
Elasticsearch基础操作演示总结
一、索引操作 (一)创建索引 创建Elasticsearch(ES)索引是在ES中存储和管理数据的重要操作之一。索引是用于组织和检索文档的结构化数据存储。 当创建Elasticsearch索引时,通常需要同时指定索引的设置(Se…...
Spring 作用域解析器AnnotationScopeMetadataResolver
博主介绍:✌全网粉丝近5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经…...
如何发布一个 NPM 包
首先初始化: npm init 文件夹结构 .gitignore Git 库忽略文件清单.npmignore 不包括在 npm 注册库中的文件清单LECENSE 模块的授权文件README.md 说明文档bin 保存模块可执行文件的文件夹doc 保存模块文档的文件夹example 保存模块实际示例lib 保存模块代码man 保存模块的手册…...
Flask小项目教程(含MySQL与前端部分)
CONTENTS 1. 环境配置2. 快速搭建Flask应用程序 1. 环境配置 首先我们在项目的根目录下创建一个 Python 虚拟环境,打开命令行输入以下指令: python -m venv venv启动虚拟环境: .\venv\Scripts\Activate.ps1如果遇到报错:.\venv…...
Eureka
大家好我是苏麟今天带来Eureka的使用 . 提供者和消费者 在服务调用关系中,会有两个不同的角色: 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务) 服务消费者:一次业务…...
STM32G070RBT6-MCU温度测量(ADC)
1、借助STM32CubeMX生成系统及外设相关初始化代码。 在以上配置后就可以生成相关初始化代码了。 /* ADC1 init function */ void MX_ADC1_Init(void) {/* USER CODE BEGIN ADC1_Init 0 *//* USER CODE END ADC1_Init 0 */ADC_ChannelConfTypeDef sConfig {0};/* USER COD…...
数据结构之带头双向循环链表
目录 链表的分类 带头双向循环链表的实现 带头双向循环链表的结构 带头双向循环链表的结构示意图 空链表结构示意图 单结点链表结构示意图 多结点链表结构示意图 链表创建结点 双向链表初始化 销毁双向链表 打印双向链表 双向链表尾插 尾插函数测试 双向链表头插 …...
adb详细教程(四)-使用adb启动应用、关闭应用、清空应用数据、获取设备已安装应用列表
adb对于安卓移动端来说,是个非常重要的调试工具。本篇介绍常用的adb指令 文章目录 一、启动应用:adb shell am start二、使用浏览器打开指定网址:adb shell am start三、杀死应用进程adb shell am force-stop/adb shell am kill四、删除应用所…...
【Spring Boot】日志文件
日志文件 一. 日志文件有什么用二. 日志怎么用三. ⾃定义⽇志打印1. 在程序中得到⽇志对象2. 使⽤⽇志对象打印⽇志3. ⽇志格式说明 四. 日志级别1. ⽇志级别有什么⽤2. ⽇志级别的分类与使⽤ 五. 日志持久化六. 更简单的⽇志输出—lombok1. 添加 lombok 依赖2. 输出⽇志3. lom…...
图像处理与计算机视觉--第五章-图像分割-Canny算子
文章目录 1.边缘检测算子分类2.Canny算子核心理论2.1.Canny算子简单介绍2.2.Canny算子边缘检测指标2.3.Canny算子基本原理 3.Canny算子处理流程3.1.高斯滤波去噪声化3.2.图像梯度搜寻3.3.非极大值抑制处理3.4.双阈值边界处理3.5.边界滞后技术跟踪3.6.Canny算子边缘检测的特点 4…...
LabVIEW开发教学实验室自动化INL和DNL测试系统
LabVIEW开发教学实验室自动化INL和DNL测试系统 如今,几乎所有的测量仪器都是基于微处理器的设备。模拟输入量在进行数字处理之前被转换为数字量。对于参加电气和电子测量课程的学生来说,了解ADC以及如何欣赏其性能至关重要。ADC的不确定性可以根据其传输…...
数据结构: 数组与链表
目录 1 数组 1.1 数组常用操作 1. 初始化数组 2. 访问元素 3. 插入元素 4. 删除元素 5. 遍历数组 6. 查找元素 7. 扩容数组 1.2 数组优点与局限性 1.3 数组典型应用 2 链表 2.1 链表常用操作 1. 初始化链表 2. 插入节点 3. 删除…...
unity 控制玩家物体
创建场景 放上一个plane,放上一个球 sphere,假定我们的球就是我们的玩家,使用控制键w a s d 来控制球也就是玩家移动。增加一个材质,把颜色改成绿色,把材质赋给plane,区分我们增加的白球。 增加组件和脚…...
指数分布优化器(EDO)(含MATLAB代码)
先做一个声明:文章是由我的个人公众号中的推送直接复制粘贴而来,因此对智能优化算法感兴趣的朋友,可关注我的个人公众号:启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法,经典的,或者是近几年…...
网站门户建设流程/seo优化师培训
3月29日,中国泛海在北京举办发布会宣布,已完成对美国国际数据集团(简称IDG)主要资产的收购,包括IDG集团旗下的国际数据公司(简称IDC)、IDG Communications。至此,中国泛海成为IDG运营…...
北京定制公交app/北京seo百科
celery 有密码的时候 清除任务 redis-cli -h host -p port -a password -n 11 ltrim transcode 0 196 没有密码的时候 redis-cli -n 11 ltrim transcode 0 196 -n 后面跟的是你要清除的第几个数据库转载于:https://www.cnblogs.com/shmily3929/p/9004781.html...
做暖暖小视频免费网站/如何制作自己的网站?
概述有时要在测试环境创建跟生产环境同个用户,但又不知道用户相关的权限,这里提供一个实用的脚本。获取创建用户脚本及权限脚本内容如下:--执行存储过程exec DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,SQLTERMINAT…...
长春火车站疫情防控最新政策/注册公司网站
本节书摘来自异步社区《调色师手册:电影和视频调色专业技法(第2版)》一书中的第1章,往返工作流程(Round-Trip workflows),作者 【美】Alexis Van Hurkman(阿列克谢凡赫克曼ÿ…...
支持wordpress空间/举出最新的网络营销的案例
1:什么是本地方法本地方法:Native Method是本地方法的意思,非java编写,比如c/c,一般用于操作底层的硬件。在java中通过本地方法接口也就是带native修饰符的方法来调用本地方法。public class NativesDemo{native publi…...
网站建设的公司合肥/百度快照如何优化
Ring已经成为我们最喜欢的DIY家庭安全系统之一,现在该公司已经重新设计了该系统的某些组件,以使其更时尚,更易于使用。最大的变化是用于布防系统的键盘,现在它具有用于警察,消防和紧急医疗的一键式按钮。定于船4月…...