SpringCloud+Sa-Token网关统一鉴权

一、网关鉴权

1.1 引入依赖

<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-reactor-spring-boot3-starter</artifactId>
    <version>1.39.0</version>
</dependency>

<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.39.0</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

1.2 鉴权接口

package com.ozo.cloud.gateway.core;

import cn.dev33.satoken.stp.StpInterface;
import com.ozo.cloud.common.base.context.CurrentUserHolder;
import com.ozo.cloud.common.base.model.LoginUser;

import java.util.ArrayList;
import java.util.List;

/**
 * 权限实现类
 *
 * @author qiangesoft
 * @date 2024-07-08
 **/
public class SaPermissionImpl implements StpInterface {

    /**
     * 获取菜单权限列表
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        LoginUser loginUser = CurrentUserHolder.current();
        return new ArrayList<>(loginUser.getMenuPermission());
    }

    /**
     * 获取角色权限列表
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        LoginUser loginUser = CurrentUserHolder.current();
        return new ArrayList<>(loginUser.getRolePermission());
    }

}

1.3 过滤器配置

package com.ozo.cloud.gateway.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.json.JSONUtil;
import com.ozo.cloud.common.base.model.ResultVO;
import com.ozo.cloud.gateway.config.properties.SecurityProperties;
import com.ozo.cloud.gateway.core.SaPermissionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * 鉴权配置
 *
 * @author qiangesoft
 * @date 2024-07-08
 **/
@EnableConfigurationProperties(SecurityProperties.class)
@Configuration
public class SaTokenConfig {

    @Autowired
    private SecurityProperties securityProperties;

    @Bean
    public StpInterface stpInterface() {
        return new SaPermissionImpl();
    }

    /**
     * 注册过滤器
     */
    @Bean
    public SaReactorFilter saServletFilter() {
        SaReactorFilter saReactorFilter = new SaReactorFilter();

        // 前置函数:在每次认证函数之前执行
        saReactorFilter.setBeforeAuth(obj -> {
                    // 设置跨域响应头
                    SaHolder.getResponse()
                            // 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
                            // .setHeader("X-Frame-Options", "SAMEORIGIN")
                            // 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
                            .setHeader("X-XSS-Protection", "1; mode=block")
                            // 禁用浏览器内容嗅探
                            .setHeader("X-Content-Type-Options", "nosniff")
                            .setHeader("Access-Control-Allow-Origin", "*")
                            .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
                            .setHeader("Access-Control-Max-Age", "3600")
                            .setHeader("Access-Control-Allow-Headers", "*");

                    // 如果是预检请求,则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS)
                            .free(r -> {
                            })
                            .back();
                })

                // 异常处理
                .setError(e -> {
                    // 由于过滤器中抛出的异常不进入全局异常处理,所以此处统一转为JSON输出前端
                    SaResponse saResponse = SaHolder.getResponse();
                    saResponse.setHeader(Header.CONTENT_TYPE.getValue(), ContentType.JSON + ";charset=" + CharsetUtil.UTF_8);
                    return JSONUtil.parseObj(ResultVO.fail(e.getMessage()));
                });

        // 指定拦截路由
        saReactorFilter.addInclude("/**")
                // 设置鉴权的接口
                .setAuth(obj -> {
                    // 登录校验 -- 拦截所有路由
                    SaRouter.match("/**", r -> StpUtil.checkLogin());
                });

        // 指定开放路由
        List<String> excludePathPatterns = securityProperties.getExcludePathPatterns();
        if (CollUtil.isNotEmpty(excludePathPatterns)) {
            saReactorFilter.addExclude(excludePathPatterns.toArray(new String[0]));
        }

        return saReactorFilter;
    }

}

1.4 子服务添加Token

package com.ozo.cloud.gateway.filter;

import cn.dev33.satoken.same.SaSameUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局过滤器,为请求添加 Same-Token
 *
 * @author qiangesoft
 * @date 2024-09-10
 */
@Component
public class ForwardAuthFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest newRequest = exchange
                .getRequest()
                .mutate()
                // 为请求追加 Same-Token 参数 
                .header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken())
                .build();
        ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
        return chain.filter(newExchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

}

二、子服务鉴权

2.1 引入依赖

<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot3-starter</artifactId>
    <version>1.39.0</version>
</dependency>

<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.39.0</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

2.2 过滤器配置

package com.ozo.cloud.common.satoken.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.same.SaSameUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.json.JSONUtil;
import com.ozo.cloud.common.base.model.ResultVO;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Sa-Token 权限认证 配置类 
 *
 * @author qiangesoft
 * @date 2024-09-10
 */
@AutoConfiguration
public class SaTokenConfig implements WebMvcConfigurer {

    /**
     * 注解鉴权拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor())
                .addPathPatterns("/**");
    }

    /**
     * 注册 Sa-Token 全局过滤器
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                // 指定拦截路由
                .addInclude("/**")

                .setAuth(obj -> {
                    // 校验 Same-Token 身份凭证
                    SaSameUtil.checkCurrentRequestToken();
                })

                // 异常处理
                .setError(e -> {
                    // 由于过滤器中抛出的异常不进入全局异常处理,所以此处统一转为JSON输出前端
                    SaResponse saResponse = SaHolder.getResponse();
                    saResponse.setHeader(Header.CONTENT_TYPE.getValue(), ContentType.JSON + ";charset=" + CharsetUtil.UTF_8);
                    return JSONUtil.parseObj(ResultVO.fail(e.getMessage()));
                });
    }

    @Bean
    @ConditionalOnMissingBean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

2.3 拦截器

package com.ozo.cloud.common.satoken.interceptor;

import cn.dev33.satoken.same.SaSameUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;

/**
 * feign拦截器, 在feign请求发出之前,加入一些操作
 *
 * @author qiangesoft
 * @date 2024-09-10
 */
public class FeignInterceptor implements RequestInterceptor {

    /**
     * 为 Feign 的 RCP调用 添加请求头Same-Token
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());

        // 如果希望被调用方有会话状态,此处就还需要将 satoken 添加到请求头中
        // requestTemplate.header(StpUtil.getTokenName(), StpUtil.getTokenValue());
    }

}

2.4 接口使用拦截器

package com.ozo.cloud.api.auth.feign;

import com.ozo.cloud.common.base.model.ResultVO;
import com.ozo.cloud.common.satoken.interceptor.FeignInterceptor;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * 授权服务调用
 *
 * @author qiangesoft
 * @date 2024-09-11
 */
@FeignClient(name = "ozo-cloud-auth", path = "/auth", configuration = FeignInterceptor.class)
public interface AuthFeignClient {

    @GetMapping("/userInfo")
    ResultVO<Object> getUserInfo();

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能辅助汽车造型设计

随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;在各个领域的应用越来越广泛&#xff0c;汽车设计行业也不例外。尤其在车辆外观造型设计中&#xff0c;AI正在成为设计师的重要助手&#xff0c;通过提供强大的工具和独特的创意方式&#xff0c;革新了传统设…

code eintegrity npm err sha512

当 npm install 出现报错的时候&#xff1a; 你应该这样去解决&#xff1a; 删除 package-lock.json 文件&#xff0c;重新执行 npm install。 问题出现的原因 EINTEGRITY 错误码表示在npm缓存中无法找到 指定sha512校验合的模块。 出现这个问题的原因是缓存不一致&…

把设计模式用起来!(4) 用不好模式?之原理不明

&#xff08;清华大学出版社 《把设计模式用起来》书稿试读&#xff09; 上一篇&#xff1a;把设计模式用起来&#xff01;&#xff08;3&#xff09;用不好模式&#xff1f;之时机不对 为什么用不好设计模式&#xff1f;——原理不明 难搞的顾客&#xff1a;“抹这种霜&#…

使用c#制作一个小型桌面程序

封装dll 首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表&#xff08;如果没有可以参考visual stdio 如何配置opencv等其他环境&#xff09; 创建完成后 系统会自动生成一些文件&#xff0c;其中 pch.cpp 先不要修改&#xff0c;pch.h中先导入自己需…

人工智能 | 基于ChatGPT开发人工智能服务平台

简介 ChatGPT 在刚问世的时候&#xff0c;其产品形态就是一个问答机器人。而基于ChatGPT的能力还可以对其做一些二次开发和拓展。比如模拟面试功能、或者智能机器人功能。 模拟面试功能包括个性化问题生成、实时反馈、多轮面试模拟、面试报告。 智能机器人功能提供24/7客服支…

GESP C++二级样题卷

一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 1.目前主流的计算机储存数据最终都是转换成&#xff08; &#xff09;数据进行储存。 ​ A&#xff0e;二进制 ​ B&#xff0e;十进制 ​ C&#xff0e; 八进制 ​ D&#xff0e;十六进制 2.已知大写字…

JDBC 编程

目录 JDBC 是什么 JDBC 的工作原理 JDBC 的使用 引入驱动 使用 常用接口和类 Connection Statement ResultSet 使用总结 JDBC 是什么 JDBC&#xff08;Java Database Connectivity&#xff09;&#xff1a;Java数据库连接&#xff0c;是一种用于执行 SQL 语句的Java…

20240920 每日AI必读资讯

阿里通义千问开源Qwen2.5系列模型&#xff1a;Qwen2-VL-72B媲美GPT-4 - Qwen2.5系列模型开源&#xff0c;包括通用语言模型和专业领域模型&#xff0c;提升知识获取、编程和数学能力。 - 模型支持长文本处理&#xff0c;生成最多8K tokens内容&#xff0c;对29种以上语言提供…

Java多线程面试精讲:源于技术书籍的深度解读

写在前面 ⭐️在无数次的复习巩固中&#xff0c;我逐渐意识到一个问题&#xff1a;面对同样的面试题目&#xff0c;不同的资料来源往往给出了五花八门的解释&#xff0c;这不仅增加了学习的难度&#xff0c;还容易导致概念上的混淆。特别是当这些信息来自不同博主的文章或是视…

SpringCloud系列之一---搭建高可用的Eureka注册中心

前言 本篇文章主要介绍的是SpringCloud相关知识、微服务架构以及搭建服务注册与发现的服务模块(Eureka)以及Eureka集群。 GitHub源码链接位于文章底部。 什么是SpringCloud Spring Cloud 是一系列框架的有序集合。 它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设…

ATGM331C-5T杭州中科微全星座定位授时模块电气参数

ATGM331C-5T 系列模块通过 UART 作为主要输出通道&#xff0c;按照 NMEA0183 的协议格式输出。 产品选型&#xff1a; 性能指标&#xff1a; 出色的定位导航功能&#xff0c;支持 BDS/GPS 卫星导航系统的单系统授时&#xff0c;以及任意组合的多系统联合定位&#xff0c;并支持…

【学习笔记】SSL/TLS证书安全机制之证书透明

1、概念 CT - Certificate Transparency&#xff0c;证书透明 2、Trying to Solve 如果意外的 CA 为我们的域名颁发证书&#xff0c;我们是不可见&#xff0c;这就是证书透明&#xff08;CT&#xff09;要解决的问题 3、How CT Works 任何CA机构颁发的所有证书的公共登记处&…

望繁信科技携流程智能解决方案亮相CNDS 2024新能源产业数智峰会

9月13日&#xff0c;CNDS 2024中国新能源产业数智峰会在北京圆满落幕。本次峰会以“走向数字新能源”为主题&#xff0c;汇聚了来自新能源领域的顶尖领袖、专家学者及知名企业代表&#xff0c;共同探讨数字化技术在新能源行业中的创新应用和发展趋势。上海望繁信科技有限公司&a…

网安标委发布敏感个人信息识别指南

9月14日全国网络安全标准化技术委员会秘书处发布《网络安全标准实践指南——敏感个人信息识别指南》 敏感个人信息识别规则&#xff1a; 一旦遭到泄露或者非法使用&#xff0c;容易导致自然人的人格尊严受到侵害、自然人的人身安全受到危害、自然人财产安全受到危害。 注意&am…

CISP备考题库(八)

CISP即“注册信息安全专业人员”&#xff0c;是面向信息安全企业、信息安全咨询服务机构、信息安全测评机构、政府机构、社会各组织、团体、大专院校以及企事业单位中负责信息系统建设、运行维护和管理工作的信息安全专业人员所颁发的专业资质证书。 更多CISP介绍&#xff1a;e…

【Git】常见命令(仅笔记)

文章目录 创建/初始化本地仓库添加本地仓库配置项提交文件查看仓库状态回退仓库查看日志分支删除文件暂存工作区代码远程仓库使用 .gitigore 文件让 git 不追踪一些文件标签 创建/初始化本地仓库 git init添加本地仓库配置项 git config -l #以列表形式显示配置项git config …

FTP、SFTP安装,整合Springboot教程

文章目录 前言一、FTP、SFTP是什么&#xff1f;1.FTP2.SFTP 二、安装FTP1.安装vsftp服务2.启动服务并设置开机自启动3.开放防火墙和SELinux4.创建用户和FTP目录4.修改vsftpd.conf文件5.启动FTP服务6.问题 二、安装SFTP1、 创建用户2、配置ssh和权限3、建立目录并赋予权限4、启动…

Elastic 的 OpenTelemetry PHP 发行版简介

作者&#xff1a;Pawel Filipczak 宣布 OpenTelemetry PHP 的 Elastic 发行版的第一个 alpha 版本。在本篇博文中了解使用 OpenTelemetry 来检测 PHP 应用程序是多么简单。 我们很高兴推出 OpenTelemetry PHP 的 Elastic Distribution 的第一个 alpha 版本。在这篇文章中&…

python植物大战僵尸项目源码【免费】

植物大战僵尸是一款经典的塔防游戏&#xff0c;玩家通过种植各种植物来抵御僵尸的进攻。 源码下载地址&#xff1a; 植物大战僵尸项目源码 提取码: 8muq