文章目录
-
- 1.Redis集群连接
- 2.网关模块sa-token集成redis集群
-
-
- 1.引入依赖
- [2.application.yml 在有sa-token的基础上集成Redis](#2.application.yml 在有sa-token的基础上集成Redis)
- 3.auth模块集成redis
- 4.启动测试
- 5.自定义权限验证接口扩展
-
- [com.sunxiansheng.club.gateway.auth.StpInterfaceImpl 这样设置就表示请求的用户为admin具有user:add权限](#com.sunxiansheng.club.gateway.auth.StpInterfaceImpl 这样设置就表示请求的用户为admin具有user:add权限)
- 6.权限认证的全局过滤器
-
- 3.GateWay实现全局异常
-
-
- 1.目录结构
- 2.Result.java
- 3.ResultCodeEnum.java
- [4.GateWayExceptionHandler.java gateway的全局异常处理器](#4.GateWayExceptionHandler.java gateway的全局异常处理器)
- 5.测试
-
- [🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)](#🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐))
-
- [🌟 亮点功能](#🌟 亮点功能)
- [📦 spring cloud模块概览](#📦 spring cloud模块概览)
- [🔗 更多信息](#🔗 更多信息)
1.Redis集群连接
1.docker启动命令(不用启动,之前配置过)
sh
docker run -d --name redis-node-1 --net=host --privileged=true \
-v /app/redis/data:/data \
-v /app/redis/redis.conf:/etc/redis/redis.conf \
redis:6.0.8 \
redis-server /etc/redis/redis.conf \
--cluster-enabled yes \
--appendonly yes \
--dir /data \
--port 6480 \
--cluster-config-file /data/nodes.conf \
--cluster-node-timeout 5000
2.常用命令
1.进入Redis容器
docker exec -it redis-node-5 /bin/bash
2.登录redis
sh
redis-cli -c -p 6480 --askpass
3.查看集群信息
sh
CLUSTER INFO
4.查看集群节点
sh
CLUSTER NODES
3.使用Redis桌面工具连接
2.网关模块sa-token集成redis集群
1.引入依赖
xml
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.37.0</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>1.37.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.application.yml 在有sa-token的基础上集成Redis
- 注意:database需要与集群设置的数据库一致
yaml
redis:
password: guest # Redis服务器密码
database: 0 # 需要与集群设置的数据库一致
timeout: 10000ms # 连接超时时间是10000毫秒
lettuce:
pool:
max-active: 8 # 最大活跃连接数,使用负值表示没有限制,最佳配置为核数*2
max-wait: 10000ms # 最大等待时间,单位为毫秒,使用负值表示没有限制,这里设置为10秒
max-idle: 200 # 最大空闲连接数
min-idle: 5 # 最小空闲连接数
cluster:
nodes:
- guest
- guest
- guest
- guest
- guest
- guest
3.auth模块集成redis
1.sun-club-auth-application-controller引入依赖
xml
<!-- Sa-Token集成redis -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>1.37.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.9.0</version>
</dependency>
2.application.yml
yaml
redis:
password: guest # Redis服务器密码
database: 0 # 需要与集群设置的数据库一致
timeout: 10000ms # 连接超时时间是10000毫秒
lettuce:
pool:
max-active: 8 # 最大活跃连接数,使用负值表示没有限制,最佳配置为核数*2
max-wait: 10000ms # 最大等待时间,单位为毫秒,使用负值表示没有限制,这里设置为10秒
max-idle: 200 # 最大空闲连接数
min-idle: 5 # 最小空闲连接数
cluster:
nodes:
guest
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: satoken
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
is-share: true
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
token-style: random-32
# 是否输出操作日志
is-log: true
token-prefix: jichi
4.启动测试
1.登录
2.验证登录
5.自定义权限验证接口扩展
com.sunxiansheng.club.gateway.auth.StpInterfaceImpl 这样设置就表示请求的用户为admin具有user:add权限
java
package com.sunxiansheng.club.gateway.auth;
import cn.dev33.satoken.stp.StpInterface;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义权限验证接口扩展
*/
@Component
public class StpInterfaceImpl implements StpInterface {
/**
* 返回此loginId拥有的权限列表
* @param loginId
* @param loginType
* @return
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
List<String> permissionList = new ArrayList<>();
permissionList.add("user:add");
return permissionList;
}
/**
* 返回此loginId拥有的角色列表
* @param loginId
* @param loginType
* @return
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
List<String> roleList = new ArrayList<>();
roleList.add("admin");
return roleList;
}
}
6.权限认证的全局过滤器
1.com.sunxiansheng.club.gateway.auth.SaTokenConfigure
java
package com.sunxiansheng.club.gateway.auth;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.UUID;
/**
* 权限认证的全局过滤器
*/
@Configuration
public class SaTokenConfigure {
@Bean
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
// 鉴权方法:每次访问进入
.setAuth(obj -> {
// 给redis 中写入数据
SaManager.getSaTokenDao().set("name" + UUID.randomUUID(), "value", 100000);
System.out.println("-------- 前端访问path:" + SaHolder.getRequest().getRequestPath());
// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
SaRouter.match("/auth/**", "/auth/user/doLogin", r -> StpUtil.checkRole("admin"));
SaRouter.match("/oss/**", r -> StpUtil.checkLogin());
SaRouter.match("/subject/subject/add", r -> StpUtil.checkPermission("subject:add"));
SaRouter.match("/subject/**", r -> StpUtil.checkLogin());
})
;
}
}
2.测试
1.网关登录
2.网关验证登录
3.GateWay实现全局异常
1.目录结构
2.Result.java
java
package com.sunxiansheng.club.gateway.entity;
import com.sunxiansheng.club.gateway.enums.ResultCodeEnum;
import lombok.Data;
/**
* Description:
* @Author sun
* @Create 2024/5/24 9:48
* @Version 1.0
*/
@Data
public class Result<T> {
private Boolean success;
private Integer code;
private String message;
private T data;
/**
* 成功返回结果
* @return
*/
public static Result ok() {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
return result;
}
/**
* 成功返回结果,携带数据
* @param data
* @return
* @param <T>
*/
public static <T> Result ok(T data) {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
result.setData(data);
return result;
}
/**
* 失败返回结果
* @return
*/
public static Result fail() {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.getDesc());
return result;
}
/**
* 失败,携带数据
* @param data
* @return
* @param <T>
*/
public static <T> Result fail(T data) {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.getDesc());
result.setData(data);
return result;
}
/**
* 扩展方法,可以返回code和message
* @param code
* @param message
* @return
*/
public static Result fail(Integer code, String message) {
Result result = new Result();
result.setSuccess(false);
result.setCode(code);
result.setMessage(message);
return result;
}
}
3.ResultCodeEnum.java
java
package com.sunxiansheng.club.gateway.enums;
import lombok.Getter;
/**
* Description: 返回结果枚举
* @Author sun
* @Create 2024/5/24 9:53
* @Version 1.0
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(500, "失败");
public int code;
public String desc;
ResultCodeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 根据code获取枚举
* @param code
* @return
*/
public static ResultCodeEnum getByCode(int code) {
for (ResultCodeEnum value : values()) {
if (value.code == code) {
return value;
}
}
return null;
}
}
4.GateWayExceptionHandler.java gateway的全局异常处理器
java
package com.sunxiansheng.club.gateway.exception;
import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sunxiansheng.club.gateway.entity.Result;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* Description: gateway的全局异常处理器
* @Author sun
* @Create 2024/6/5 13:18
* @Version 1.0
*/
@Component
public class GateWayExceptionHandler implements ErrorWebExceptionHandler {
// 组合一个ObjectMapper对象,将Result转化为bytes数组
private ObjectMapper objectMapper = new ObjectMapper();
/**
*
* @param serverWebExchange 可以获取请求和响应
* @param throwable 可以获取异常信息
* @return
*/
@Override
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
// 获取请求和响应
ServerHttpRequest request = serverWebExchange.getRequest();
ServerHttpResponse response = serverWebExchange.getResponse();
// 定义状态码和信息
Integer code = 200;
String message = "";
// 如果抛出的异常是SaToken类型的,就返回401的状态码
if (throwable instanceof SaTokenException) {
code = 401;
message = "用户无权限";
} else {
// 如果是其他的异常,就返回500的状态码
code = 500;
message = "服务器繁忙";
throwable.printStackTrace();
}
// 构建Result
Result result = Result.fail(code, message);
// 返回json类型的数据
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
return response.writeWith(Mono.fromSupplier(() -> {
// 构建一个数据工厂,一会返回
DataBufferFactory dataBufferFactory = response.bufferFactory();
byte[] bytes = null;
// 将结果转化为byte数组
try {
bytes = objectMapper.writeValueAsBytes(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 返回
return dataBufferFactory.wrap(bytes);
}));
}
}
5.测试
🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)
轻松高效的现代化开发体验
Sun Frame 是我个人开源的一款基于 SpringBoot 的轻量级框架,专为中小型企业设计。它提供了一种快速、简单且易于扩展的开发方式。
我们的开发文档记录了整个项目从0到1的任何细节,实属不易,请给我们一个Star!🌟
您的支持是我们持续改进的动力。
🌟 亮点功能
- 组件化开发:灵活选择,简化流程。
- 高性能:通过异步日志和 Redis 缓存提升性能。
- 易扩展:支持多种数据库和消息队列。
📦 spring cloud模块概览
- Nacos 服务:高效的服务注册与发现。
- Feign 远程调用:简化服务间通信。
- 强大网关:路由与限流。
常用工具
- 日志管理:异步处理与链路追踪。
- Redis 集成:支持分布式锁与缓存。
- Swagger 文档:便捷的 API 入口。
- 测试支持:SpringBoot-Test 集成。
- EasyCode:自定义EasyCode模板引擎,一键生成CRUD。
🔗 更多信息
- 开源地址 :Gitee Sun Frame
- 详细文档 :语雀文档