Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录

OAuth 2.0第三方登录

OAuth 2.0 是一种授权协议,允许第三方应用在不暴露用户密码的情况下访问用户的资源。它通常用于第三方登录场景,例如使用GitHub、Google等社交平台进行登录。

sa-token框架中,OAuth 2.0第三方登录可以通过集成sa-token-oauth2模块来实现,并且可以结合sa-token的安全特性来增强安全性。

导入依赖

首先,在你的pom.xml文件中添加必要的依赖,包括sa-token核心模块、MyBatis、数据库驱动等,特别是要导入sa-token-oauth2模块。

<dependencies><!-- sa-token 核心模块 -->//如果你使用的是 SpringBoot 3.x,只需要将 sa-token-spring-boot-starter 修改为 sa-token-spring-boot3-starter 即可。<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.40.0</version></dependency><!-- Sa-Token OAuth2.0 模块 --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-oauth2</artifactId><version>1.40.0</version></dependency><!-- MyBatis Spring Boot Starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><!-- MySQL Driver --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Lombok  --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- JSON  --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- Sa-Token SSO  --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-sso-spring-boot-starter</artifactId><version>1.40.0</version></dependency>
</dependencies>

配置 application.yml

application.yml中配置sate-token、数据库连接信息以及OAuth 2.0提供商的信息。

server:port: 8080 # 应用端口sa-token:token-name: satoken  # 指定token的名称,默认是satokentimeout: 7200        # 超时时间 (单位秒),这里是2小时is-read-body: true   # 是否读取请求体,默认是trueis-concurrent: false # 是否允许多端登录,默认是falseis-share: true       # 是否共享Session信息,默认是truetoken-style: uuid    # Token生成风格,默认是uuidsso:login-url: /sso/login # 单点登录入口地址logout-url: /sso/logout # 单点注销入口地址callback-url: /sso/callback # 单点登录回调地址oauth2:client:github:client-id: your-client-id # 替换为你的GitHub Client IDclient-secret: your-client-secret # 替换为你的GitHub Client Secretredirect-uri: "{baseUrl}/oauth2/code/github" # 回调地址模板scope: read:user,user:email # 请求的范围user-info-uri: https://api.github.com/user # 用户信息获取URLauthorization-uri: https://github.com/login/oauth/authorize # 授权URLtoken-uri: https://github.com/login/oauth/access_token # Token获取URLspring:datasource:url: jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTCusername: your_usernamepassword: your_passworddriver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/*.xml # MyBatis Mapper XML 文件位置type-aliases-package: com.example.demo.entity # 实体类包路径

 初始化数据

你可以使用以下SQL语句初始化一些测试数据:

CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(255) NOT NULL UNIQUE,password VARCHAR(255) NOT NULL
);CREATE TABLE permissions (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL
);CREATE TABLE user_permissions (user_id BIGINT NOT NULL,permission_id BIGINT NOT NULL,FOREIGN KEY (user_id) REFERENCES users(id),FOREIGN KEY (permission_id) REFERENCES permissions(id)
);INSERT INTO users (username, password) VALUES ('admin', 'password');
INSERT INTO permissions (name) VALUES ('admin:manage'), ('user:view');INSERT INTO user_permissions (user_id, permission_id) 
SELECT u.id, p.id FROM users u, permissions p WHERE u.username = 'admin' AND p.name IN ('admin:manage', 'user:view');

DTO类

创建一个简单的DTO类用于接收登录请求的数据。

UserLoginDTO.java
package com.example.demo.dto;public class UserLoginDTO {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

创建实体类

创建UserPermission实体类,并映射到数据库表。

User.java
package com.example.demo.entity;import lombok.Data;
import java.util.Set;@Data
public class User {private Long id; // 用户IDprivate String username; // 用户名private String password; // 密码private Set<String> permissions; // 权限集合(简化版,直接存储权限字符串)
}
Permission.java
package com.example.demo.entity;import lombok.Data;@Data
public class Permission {private Long id;private String name; // 权限名称
}

创建Mapper接口

创建UserMapper接口来访问数据库。

UserMapper.java
package com.example.demo.mapper;import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;@Mapper
public interface UserMapper {/*** 根据用户名查找用户及其权限* @param username 用户名* @return 用户对象*/@Select("SELECT u.id, u.username, u.password FROM users u WHERE u.username = #{username}")User findByUsername(@Param("username") String username);/*** 查找用户的权限列表* @param userId 用户ID* @return 权限集合*/@Select("SELECT p.name FROM user_permissions up JOIN permissions p ON up.permission_id = p.id WHERE up.user_id = #{userId}")List<String> findPermissionsByUserId(@Param("userId") Long userId);
}

创建Service层

创建UserService接口及其实现类。

UserService.java
package com.example.demo.service;import com.example.demo.entity.User;public interface UserService {User findByUsername(String username); // 根据用户名查找用户
}
UserServiceImpl.java
package com.example.demo.service.impl;import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.HashSet;
import java.util.List;
import java.util.Set;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic User findByUsername(String username) {// 查找用户基本信息User user = userMapper.findByUsername(username);if (user != null) {// 查找用户的权限列表List<String> permissionNames = userMapper.findPermissionsByUserId(user.getId());Set<String> permissions = new HashSet<>(permissionNames);user.setPermissions(permissions);}return user;}
}

创建Controller层

创建LoginController类来处理用户的登录请求。

LoginController.java
package com.example.demo.controller;import com.example.demo.dto.UserLoginDTO;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.info.SaTokenInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
public class LoginController {@Autowiredprivate UserService userService; // 自动注入UserService/*** 处理用户登录请求* @param loginDTO 登录信息* @return 登录结果*/@PostMapping("/login") // 映射HTTP POST请求到/login路径public ResponseEntity<String> login(@RequestBody UserLoginDTO loginDTO) { // 接收JSON格式的登录信息String username = loginDTO.getUsername(); // 获取用户名String password = loginDTO.getPassword(); // 获取密码// 查找用户User user = userService.findByUsername(username); // 从数据库查找用户if (user != null && password.equals(user.getPassword())) { // 验证密码StpUtil.login(user.getId()); // 登录用户,参数为用户IDfor (String permission : user.getPermissions()) {StpUtil.setPermission(permission); // 设置用户权限}SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); // 获取token信息return ResponseEntity.ok("登录成功, Token: " + tokenInfo.getTokenValue()); // 返回登录成功消息}return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户名或密码错误"); // 返回错误消息}
}

权限校验

使用注解@SaCheckPermission对需要权限控制的方法进行保护。

AdminController.java
package com.example.demo.controller;import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/admin")
public class AdminController {/*** 管理后台接口* @return 管理后台页面内容*/@SaCheckPermission(value = "admin:manage") // 检查当前用户是否有"admin:manage"权限@GetMapping("/manage") // 映射GET请求到/admin/manage路径public String manage() {return "管理后台"; // 如果权限检查通过,则返回管理后台页面内容}
}

OAuth 2.0集成

对于OAuth 2.0第三方登录,我们可以使用sa-token-oauth2模块提供的功能来实现。

OAuth2Controller.java
package com.example.demo.controller;import cn.dev33.satoken.oauth2.logic.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.AuthTokenModel;
import cn.dev33.satoken.oauth2.model.UserInfoModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Handle;
import cn.dev33.satoken.oauth2.model.SaClientModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@RestController
@RequestMapping("/oauth2")
public class OAuth2Controller {@GetMapping("/login/github")public void loginGithub(HttpServletResponse response) throws IOException {// GitHub登录SaOAuth2Config config = SaOAuth2Manager.getConfig(SaOAuth2Consts.GITHUB);SaOAuth2Handle.redirectTo(config);}@GetMapping("/code/github")public String callbackGithub(@RequestParam String code, @RequestParam String state) {// GitHub回调处理SaOAuth2Config config = SaOAuth2Manager.getConfig(SaOAuth2Consts.GITHUB);CodeModel codeModel = new CodeModel(code, state);AccessTokenModel accessTokenModel = SaOAuth2Handle.getAccessToken(config, codeModel);UserInfoModel userInfoModel = SaOAuth2Handle.getUserInfo(config, accessTokenModel);// 这里可以添加将用户信息保存到数据库的逻辑return "登录成功,欢迎:" + userInfoModel.getUsername();}
}

总结

以上步骤详细描述了如何在Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化新零售与 AI 大模型,如何重塑大健康赛道?​

在数字化浪潮中&#xff0c;大健康赛道正经历深刻变革。数字化新零售营销模式的兴起&#xff0c;与 AI 大模型的强大能力相结合&#xff0c;为大健康领域带来了全新的发展机遇。 数字化新零售营销模式融合线上线下&#xff0c;运用大数据、云计算分析消费者行为&#xff0c;实…

高速PCB设计(布线设计)

以下是针对高速PCB布线设计的综合笔记&#xff0c;结合用户提供的设计规范及行业通用原则整理而成&#xff1a; 一、关键信号布线原则 布线优先级 顺序&#xff1a;射频信号&#xff1e;中/低频信号&#xff1e;时钟信号&#xff1e;高速信号射频信号需包地处理&#xff0c;线…

宇树ROS1开源模型在ROS2中Gazebo中仿真

以GO1为例 1. CMakelists.txt更新语法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…

嵌入式学习第二十四天--网络 服务器

服务器模型 tcp服务器: socket bind listen accept recv/send close 1.支持多客户端访问 //单循环服务器 socket bind listen while(1) { accept while(1) { recv/send } } close 2.支持多客户端同时访问 (并发能力) 并发服务器 socket bind …

使用GPTQ量化Llama-3-8B大模型

使用GPTQ量化8B生成式语言模型 服务器配置&#xff1a;4*3090 描述&#xff1a;使用四张3090&#xff0c;分别进行单卡量化&#xff0c;多卡量化。并使用SGLang部署量化后的模型&#xff0c;使用GPTQ量化 原来的模型精度为FP16&#xff0c;量化为4bit 首先下载gptqmodel量化…

防汛应急包,快速响应,守护安全

根据中国水利部统计&#xff0c;自1949年以来&#xff0c;我国几乎每年都面临洪水威胁&#xff0c;其中20世纪90年代后洪涝灾害频率显著增加&#xff0c;仅1990-2009年间就发生超4000起较大灾害&#xff0c;直接经济损失近3万亿元&#xff0c;受灾人口达20亿人次。在2020年长江…

从 Vue 到 React:理解作用与副作用

作用 VS 副作用 响应式作用&#xff1a; 响应式作用是 Vue 响应式系统的一部分&#xff0c;它指的是跟踪函数的依赖关系&#xff0c;并在它们的值发生变化时重新运行该函数的过程。watchEffect 是最直接的创建作用的方式&#xff08;如 watch 和 computed&#xff09;。 副作…

a = b c 的含义

简单一句话&#xff1a; result condition && value; condition 为真取 value的值&#xff0c;condition为假就取condition的值&#xff0c;真取后假取前 // 示例 1: b 为真值 let b 1; let c 2; let a b && c; console.log(a); // 输出: 2// 示例 2: b 为…

【大模型系列】llama.cpp本地运行大模型

上一篇链接: 【大模型系列】使用ollama本地运行千问2.5模型 我们讲了ollama本地运行大模型&#xff0c;这里我们介绍另一种本地运行大模型的方法&#xff1a;llamacpp 软件下载 下载地址&#xff1a;https://github.com/ggml-org/llama.cpp/releases 下载cpu版本的llamacpp&a…

PyQt基础——简单的图形化界面(窗口)

一、代码展示 import sysfrom PyQt6.QtGui import QPixmap from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QLineEdit, QPushButton from PyQt6 import uic from PyQt6.QtCore import Qt# 封装一个我的窗口类 class MyWidget(QWidget):def __init__(self):supe…

泰山派开发之—Ubuntu24.04下Linux开发环境搭建

简介 最近翻到了吃灰已久的泰山派&#xff0c;是刚出来的时候用优惠券买的&#xff0c;当时价格挺便宜的&#xff0c;最近给它翻出来了&#xff0c;打算试试做个项目。买的泰山派容量是2G16G&#xff0c;SOC芯片使用的是RK3566&#xff0c;搭载1TOP算力的NPU&#xff0c;并且具…

HTTP 协议中常见的错误状态码(详细介绍)

以下是 HTTP 协议中常见的错误状态码及其原因的总结&#xff0c;按错误类型分类整理&#xff1a; 4xx 客户端错误 400 Bad Request 原因&#xff1a;请求格式错误&#xff0c;服务器无法解析。常见场景&#xff1a; 请求头或请求体语法错误&#xff08;如 JSON/XML 格式错误…

kkFileView文件预览组件部署说明

kkFileView组件部署流程指南 在数字化办公与文件管理场景中&#xff0c;在线文件预览功能极为关键。kkFileView作为一款优秀的开源在线文件预览组件&#xff0c;支持多种格式文件的预览&#xff0c;为企业和开发者提供了便捷的解决方案。下面将详细介绍其部署步骤。 一、前期准…

[React Native]Stack、Tab和Drawer导航器详解

对于StackNavigator&#xff0c;网页[1]提到它用于页面间的层级跳转&#xff0c;使用栈结构管理页面。网页[4]和[8]详细说明了navigationOptions的配置&#xff0c;比如标题、头部样式等。网页[3]展示了如何在Stack中嵌入Tab导航&#xff0c;这可以作为组合使用的例子。 TabNa…

激光雷达产业观察--速腾聚创发展脉络2025.3.14

一.发展历程 1.1 企业创立 速腾聚创的创立可追溯至2014年8月28日&#xff0c;这家充满活力的高科技企业诞生于中国深圳。公司创始人邱纯鑫是一位富有远见的企业家&#xff0c;他的创业之路充满了创新精神和技术洞察力。 邱纯鑫的创业灵感源于他在哈尔滨工业大学深圳校区的学…

Kubernetes 网络方案全解析:Flannel、Calico 与 Cilium 对比与选择

文章目录 Kubernetes 网络方案全解析&#xff1a;Flannel、Calico 与 Cilium 对比与选择Flannel —— 轻量级基础网络简介核心特性适用场景 Calico —— 高性能与安全兼备的成熟方案简介核心特性适用场景 Cilium —— 基于 eBPF 的下一代网络方案简介核心特性适用场景 深入对比…

OpenCV实现图像分割与无缝合并

一、图像分割核心方法 1、阈值分割 #include <opencv2/opencv.hpp> using namespace cv; int main() {Mat img imread("input.jpg", IMREAD_GRAYSCALE);Mat binary;threshold(img, binary, 127, 255, THRESH_BINARY); // 固定阈值分割imwrite("binary.…

计算机视觉算法实战——驾驶员分心检测(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​ 1. 领域简介&#xff1a;驾驶员分心检测的意义与挑战 驾驶员分心检测是智能驾驶安全领域的重要研究方向。据统计&#xff0c;全球每…

scoop退回软件版本的方法

title: scoop退回软件版本的方法 date: 2025-3-11 23:53:00 tags: 其他 前言 在软件更新后&#xff0c;如果出现了很影响使用体验的问题&#xff0c;那么可以把软件先退回以前的版本进行使用&#xff0c; 但是scoop本身并没有提供直接让软件回退版本的功能&#xff0c;因此…

OpenRewrite配方之import语句的顺序——org.openrewrite.java.OrderImports

org.openrewrite.java.OrderImports 是 OpenRewrite 工具库中的一个重要规则(Recipe),专为 Java 项目设计,用于自动化调整 import 语句的顺序,使其符合预定义的代码规范。从而提高代码的一致性和可读性。 核心功能 排序规则: 静态导入优先:默认将静态导入(import stati…