目录
网关传递用户id:根据不同的登录类型使用不同的StpUtil工具类
前言
微服务拆分一般有两种模式:maven聚合和独立project
- maven聚合:每个服务是一个独立的maven模块,所有的模块通过maven聚合到一个父工程中
- 独立project:每个服务是一个独立的project项目,并且这些project内部还能拆分模块。一般把这些多个project放在同一个文件夹中
第一种方式较为简单,第二种适合大型项目,较为复杂。本文采用第一种:maven聚合的方式,
微服务一般有两种鉴权模式:即网关统一鉴权和每个服务独自鉴权
- 网关统一鉴权:在网关处进行权限校验,如果权限具备则转发给目标服务,否则直接返回错误,其他服务只编写业务代码,而不关注权限。
- 服务各自鉴权:网关直接转发请求到目标,目标服务完成自己的接口鉴权。该模式与单体架构类似
两种方式都有各自的优缺点。本文采用第一种方式是因为第二种方式与单体架构类似,咱已经掌握,就不必花费心思了。
项目描述
使用技术
语言:java(jdk17)
框架版本:
- springboot:3.2.4;
- springcloud:2023.0.3;
- spring.cloud.alibaba:2023.0.0.0-RC1
- sa-token:1.39.0(boot3)
- nacos:2.4.3
项目结构
- api:主要封装feign的接口,以及feign传递的参数模型还有feign的配置,该模块被其他需要发送feign调用的服务集成
- auth:认证授权服务,目前仅实现了登录功能
- common:通用工具模块,主要封装一些通用的工具类,以及依赖。该模块被其他模块和服务集成
- gateway:网关服务,主要用于服务鉴权,路由转发,负载均衡
- system:系统服务,本项目系统的业务功能。
- script:脚本,比如数据库脚本
- ui:前端项目
- doc:文档,比如软件需求规格说明书,软件使用手册等(未实现)
要点
项目鉴权一般需要解决两个问题:接口鉴权和用户信息传递。
为什么要解决这两个问题?
接口鉴权:自然就是判断当前请求是否具有权限访问服务的接口。如果没有权限就拒接访问。
用户信息传递:服务需要获取当前请求是哪个用户,因为有些业务需要记录用户操作
怎么解决这两个问题?
对于服务各自鉴权模式来说就很简单,因为每个服务都集成了satoken,接口鉴权和用户信息获取跟单体模式一样简单(但是feign请求还是需要配置拦截器添加token请求头)。这里就不阐述了。
但是网关统一鉴模式要解决这两个问题就比较麻烦。其中实现大概要点如下:
- 在网关处配置satoken鉴权,实现转发服务之前校验权限
- 在网关处解析token,拿到用户ID,添加到请求头中。然后再转发给目标服务
- 在通用模块中配置MVC拦截器,判断请求头中是否具有用户id,如果有就存到线程变量中。
- 在api模块中配置feign拦截器,判断当前线程变量中是否具有用id,如果有就添加到请求头中
是不是感觉简单?其实不然,真实操作的时候有较多的坑!!!(;´༎ຶД༎ຶ`)
实现
前期准备
依赖准备
统一依赖版本
父模块主要用于统一依赖版本,其pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>sc-common</module>
<module>sc-system</module>
<module>sc-gateway</module>
<module>sc-auth</module>
<module>sc-api</module>
</modules>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>3.2.4</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<groupId>com.schoolcolud</groupId>
<artifactId>SchoolCloud</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.cloud.version>2023.0.3</spring.cloud.version>
<spring.cloud.alibaba.version>2023.0.0.0-RC1</spring.cloud.alibaba.version>
<mybatis.version>3.0.3</mybatis.version>
<mysql.version>8.0.31</mysql.version>
<hutool.version>5.8.25</hutool.version>
<satoken.version>1.39.0</satoken.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>public</id>
<name>阿里云公共仓库</name>
<!-- <url>https://repo.maven.apache.org/maven2</url>-->
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</project>
模块依赖
common模块依赖
<dependencies>
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- 服务注册与发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- 配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
api模块依赖
<dependencies>
<!-- 远程调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.schoolcolud.common</groupId>
<artifactId>sc-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
auth模块依赖
<dependencies>
<dependency>
<groupId>com.schoolcolud.common</groupId>
<artifactId>sc-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 验证码-->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson&l