springcloud-gateway-2-鉴权

目录

一、跨域安全设置

二、GlobalFilter实现全局的过滤与拦截。

三、GatewayFilter单个服务过滤器

1、原理-官方内置过滤器

2、自定义过滤器-TokenAuthGatewayFilterFactory

3、完善TokenAuthGatewayFilterFactory的功能

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

四、总结


续前篇,介绍了gateway中实现了动态路由转发功能以后,本篇将介绍何在spring gateway中实现鉴权的功能。

鉴权目的就是为了安全。仅开放给指定的有权限的合适的人资源。网关在提供统一的路由解析的同时,会提供统一和token认证,统一的加解密,统一的身份认证等功能。

一般作为网关,需要转发的服务较多,在服务级权限分类上,可能有这么几种类理:

  • 直接放行,比如静态资源。当然这种一般建议直接在nginx跳转,减少网关流量。但是还是会有一些比如login等,需要直接放行的接口。
  • 需要jwt等TOKEN验证。在请求头中携带token字段,用来验证是否有合适的身份。这个用得比较多,通常会把token存到redis中。
  • 需要sign验证。在请求头或url参数中携带sign验证字段。可能采用md5等计算方法。
  • 需要jwt验证,同时需要对报文进行加密传输。比如采用rsa\m3等加密。
  • 除此之外还有黑名单。需要全局生效

针对上面的需求,我们就可以利用下面这两个过滤器进行分类实现: 

  • GlobalFilter 全局过滤器
  • GatewayFilter 将应用到单个路由或者同一个分组中的路由上

一、跨域安全设置

如果生产环境限定域名的,可以配置。如果前后端分离的,一般要设置允许所有的网站访问。

    gateway:globalcors:cors-configurations:'[/**]': # 匹配所有请求allowedOrigins: "*" #跨域处理 允许所有的域allowedMethods: # 支持的方法- GET- POST- PUT- DELETE

二、GlobalFilter实现全局的过滤与拦截。

利用GlobalFilter实现全局过滤-黑名单功能,新建一个类,继承GlobalFilter就好了:

package com.iuyun.gateway.filter;import com.iuyun.gateway.services.IpService;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.Objects;/*** 这是自定义的全局过滤器* 1、 黑名单禁止访问* 2、 ...*/
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {@ResourceIpService ipService;@Overridepublic int getOrder() {// TODO Auto-generated method stubreturn -1;   // 数字越小,优先级越高。定义-1为最高优先级}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();System.out.println("MyGlobalFilter: uri:" + request.getURI() );// 获取请求ipString ip = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();// 1 调用服务,检查是否在黑名单池内.如果是黑名单,则中断。if (ipService.isIpBlocked(ip)) {exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);return exchange.getResponse().setComplete();}// 2 执行其他全局服务// 3 放行return chain.filter(exchange);}}

调用到的方法(模拟): 


@Service
public class IpService {/***  根据IP地址查询数据库中的黑白名单列表,判断是否被阻止* */public boolean isIpBlocked(String ipAddress) {System.out.println("ip:"+ipAddress);// 将ip去redis或者数据库中查找,是否在黑名单内。//    return count >0; // 只要出现条数大于0,则表示在默名单内// 这里面是模拟,写死了return ipAddress.equals("192.168.2.3");}
}

 测试:我们从不同IP来访问不同的服务,可以看到都会被执行:

 当IP在黑名单内时,会返回403:

三、GatewayFilter单个服务过滤器

将应用到单个路由或者同一个分组中的路由上。

1、原理-官方内置过滤器

我们先看一下官方的示例:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue
表示使用过滤器AddResponseHeader,=后面的是参数,它接收一个名称和一个正则表式。

那我们去看看它是怎么实现的:

看了一下其他的filterFactory,都差不多,简单总结一下:

1、命名:PrefixPathGatewayFilterFactory => XXXXGatewayFilterFactory

2、继承抽象类 AbstractGatewayFilterFactory<PrefixPathGatewayFilterFactory.Config> 

3、重写方法GatewayFilter apply(Config config)

我们如果照抄一份,是不是就可以实现自定义过滤器了呢?下面我就来试一下。

2、自定义过滤器-TokenAuthGatewayFilterFactory

1)编写一个GatewayFilterFactory(复制AddResponseHeaderFilterFactory的内容,改个名)


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String value = ServerWebExchangeUtils.expand(exchange, config.getValue());exchange.getResponse().getHeaders().add(config.getName(), value);System.out.println("config.getName():" + config.getName());System.out.println("value:" + value);return chain.filter(exchange);}@Overridepublic String toString() {return filterToStringCreator(TokenAuthGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();}};}}

2)application配置

3)重启,看一下测试效果

 

先走了全局过滤器,然后这个se-a服务走了这个filter,打印了变量。

这就证明了可以这样实现自定义过滤器,那么,我们在gateway中做任何的校验就方便了。且predicates和filters是可以使用多个进行组合的:

filters: - StripPrefix=1- TokenAuth=jwt,Hello- AddResponseHeader=jwt,Hello1

这样就使用了三个filter。

3、完善TokenAuthGatewayFilterFactory的功能

(这个过程就根据自己的需要进行编写吧,比如,采用RSA加密,sm3加密,验证JWT等)

这里我模拟一个需求如下:

每次请求必须在请求头或url参数中传递一个token字段。

如果没有直接拒绝请求.如果token不对,返回401。

只有token正确,才放行,并在请求头添加一个userId字段传递给被调用的微服务。

要想实现直接拒绝不响应,可以使用predicatie,不符合条件就返回404了

- id: service-auri: lb://service-a # lb:服务名称。表示调用nacos注册的服务名称为service-b的服务predicates:- Path=/se-a/**- Header=token,\d+filters: - StripPrefix=1  - TokenAuth=jwt,Hello

但是这样并不友好,有统一返回值是现在流行的做法。且万一在prdicates中忘记加这个Header了,在filter中就因为没有token字段而出错。所以为了防止出错在filter还是要再进行一次token是否为空的校验,那么就干脆都在filter中实现吧。


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String value = ServerWebExchangeUtils.expand(exchange, config.getValue());  // config.getValue()  config.getName()String headerToken = exchange.getRequest().getHeaders().getFirst("token");String urlToken = exchange.getRequest().getQueryParams().getFirst("token");// 优先使用header中的token,其次是url中的token,如果没有则继续为nullString reqToken =StringUtils.isBlank(headerToken)? urlToken:headerToken;// 检查token是否存在且正确,一般都需要去调auth服务,从数据库或redis拿到密码并校验String userId = TokenCheck.JwtCheck(reqToken);if(StringUtils.isBlank(reqToken) || StringUtils.isBlank(userId)){// 返回状态码401表示未授权exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}// 运行到这里,表示token计算正确。将UserID添加到header进行传递ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> httpHeaders.add("userId",userId)).build();return chain.filter(exchange.mutate().request(request).build());}@Overridepublic String toString() {return filterToStringCreator(TokenAuthGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();}};}}
@Component
public class TokenCheck {public static String JwtCheck(String token){// 去redis获取是否存在这个token,如果不存在,则表示未登陆或登陆已过期。// 如果没存到redis,则这里要粗数据库调user表,查询用户的密码,并调用jwt的方法计算密码是否正确// 这里做模拟,先写死。如果正确,返回一个userId =if(!StringUtils.isBlank(token) && !token.equals("jwt11234")){return null;}else{// 这里写死,返回一个userIDreturn "admin";}}
}

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

也可以多个服务使用同一个过滤器。

四、总结

由于本篇重点是讲gateway中如何实现鉴权,所以并未展开介绍。在上面的示例中,我们并没有真的实现jwt验证等,只是做了一个固定值的返回。后面我们将继续介绍实现jwt的验证。

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

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

相关文章

关于“Python”的核心知识点整理大全39

目录 ​编辑 14.1.5 将 Play 按钮切换到非活动状态 game_functions.py 14.1.6 隐藏光标 game_functions.py game_functions.py 14.2 提高等级 14.2.1 修改速度设置 settings.py settings.py settings.py game_functions.py 14.2.2 重置速度 game_functions.py 1…

饥荒Mod 开发(二一):超大便携背包,超大物品栏,永久保鲜

饥荒Mod 开发(二十)&#xff1a;显示打怪伤害值 源码 游戏中的物品栏容量实在太小了&#xff0c;虽然可以放在箱子里面但是真的很不方便&#xff0c;外出一趟不容易看到东西都不能捡。实在是虐心。 游戏中的食物还有变质机制&#xff0c;时间长了就不能吃了&#xff0c;玩这个游…

【高数定积分求解旋转体体积】 —— (上)高等数学|定积分|柱壳法|学习技巧

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 Shell method Setting up the Integral 例题 Example 1: Example 2: Example 3: Computing…

Linux--shell练习题

1、写一个 bash脚本以输出数字 0 到 100 中 7 的倍数(0 7 14 21...)的命令。 vim /shell/homework1.sh #!/bin/bash for num in {0..100} doif [[ num%7 -eq o ]];thenecho $numfi done执行输出脚本查看输出结果 输出结果&#xff1a; 2、写一个 bash脚本以统计一个文本文件…

LLM之RAG实战(七)| 使用llama_index实现多模态RAG

一、多模态RAG OpenAI开发日上最令人兴奋的发布之一是GPT-4V API&#xff08;https://platform.openai.com/docs/guides/vision&#xff09;的发布。GPT-4V是一个多模态模型&#xff0c;可以接收文本/图像&#xff0c;并可以输出文本响应。最近还有一些其他的多模态模型&#x…

flutter 实战 之 dio小实践

我们要对dio进行封装 class HttpRequest {static Future request(String url,{String method "get",Map<String,dynamic>? params})async{// 创建dio实例BaseOptions baseOptions BaseOptions(baseUrl: base_url,connectTimeout: Duration(seconds: 1));fi…

50 个具有挑战性的概率问题 [04/50]:尝试直至首次成功

一、说明 你好&#xff0c;我最近对与概率相关的问题产生了兴趣。我偶然发现了 Frederick Mosteller 所著的《五十个具有挑战性的概率问题及其解决方案》这本书。我认为创建一个系列来讨论这些可能作为面试问题出现的迷人问题会很有趣。每篇文章仅包含 1 个问题&#xff0c;使其…

【四】【C语言\动态规划】地下城游戏、按摩师、打家劫舍 II,三道题目深度解析

动态规划 动态规划就像是解决问题的一种策略&#xff0c;它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题&#xff0c;并将每个小问题的解保存起来。这样&#xff0c;当我们需要解决原始问题的时候&#xff0c;我们就可以直接利…

一款超好看流行的HTML随机视频播放背景引导页面源码

前言 今天宋佳乐博客给大家带来一款2024新版视频背景网址导航引导页面源码带背景动态HTML源码 源码介绍 2024新版视频背景网址导航引导页面源码带背景动态HTML源码&#xff0c;非常的炫酷&#xff0c;有需要的自行去体验吧&#xff0c;还是非常不错的 演示地址&#xff1a;点…

《xHCI 1.2》3体系结构概览

3.2 xHCI数据结构 3.2.1 Device Context Base Address Array 3.2.2 Device Context 3.2.3 Slot Context

keystone和beaengine的编译

编译Keystone 根据github的文档编译不出来&#xff0c;所以还是用CMake项目转成Visual Studio的项目来编译 1、下载源码 https://github.com/keystone-engine/keystone clone或者直接下载zip都行 2、CMake创建Visual Studio项目 下载和安装CMake就不细说了&#xff0c;在…

网络7层架构

网络 7 层架构 什么是OSI七层模型&#xff1f; OSI模型用于定义并理解数据从一台计算机转移到另一台计算机&#xff0c;在最基本的形式中&#xff0c;两台计算机通过网线和连接器相互连接&#xff0c;在网卡的帮助下共享数据&#xff0c;形成一个网络&#xff0c;但是一台计算…

正餐---二叉树的OJ题

目录​​​​​​​ 前言&#x1f36f; 1. 检查两颗树是否相同&#x1f947; 1.1 思路分析&#x1fa99; 1.2 代码实现&#x1f9f0; 2. 单值二叉树&#x1f332; 2.1 思路分析&#x1f52e; 2.2 代码实现&#x1f488; 3. 二叉树的前序遍历&#x1f39f;️ 3.1 思路分…

【数据结构】线性表

一.线性表 1.定义&#xff1a; n个同类型数据元素的有限序列&#xff0c;记为 L为表名&#xff0c;i为数据元素在线性表中的位序&#xff0c;n为线性表的表长&#xff0c;n0时称为空表。 2.数据元素之间的关系&#xff1a; 直接前驱和直接后继 3.抽象数据类型线性表的定义…

git首次使用--去公司第一次拉取

文章目录 一&#xff0c; 在企业中首次拉取项目二&#xff0c;提交项目1. 提交----新添加的文件2. 将分支上的代码同步到master3. 提交----更改后的文件 三&#xff0c;常见问题1. Git Pull Failed 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一&am…

固定效应模型-以stata为工具

固定效应模型-以stata为工具 文章目录 1.固定效应模型2. 模型原理3. `stata`代码实现1.固定效应模型 固定效应模型(Fixed Effects Model)是一种面板数据分析方法,通过引入个体固定效应来控制个体间的异质性,并更准确地估计解释变量对因变量的影响。它在许多经济、社会科学…

qt项目-《图像标注软件》源码阅读笔记-类图

目录 1. 开源项目链接 2. 项目界面 3. 项目类图 3.1 形状的绘制及形状的存储 3.2 主窗口中心组件的界面管理 3.3 Command负责实现撤销和重做功能 3.4 其他类 3.5 枚举 3.5.1 Status 主窗口的状态变量 3.5.2 Mode 主窗口模式状态变量 3.5.3 shapeStatus 中心组件状态…

josef约瑟 电流继电器 RL-D1 电压AC220V 整定范围0-9.99AAC

系列型号 RL-D1型电流继电器&#xff1b; RL-D2型电流继电器&#xff1b; 基本参数 RL-D系列电流继电器用于发电机、变压器和输电线的过负荷和短路保护装置中作为启动元件。本继电器为集成电路型继电器&#xff0c;精度高、功耗小、动作时间快&#xff0c; 返回系数高、整定…

AndroidStudio无法新建aidl文件解决办法

我用的 AS 版本是 Android Studio Giraffe | 2022.3.1 Build #AI-223.8836.35.2231.10406996, built on June 29, 2023 右键新建 aidl 文件&#xff0c; 提示 (AIDL File)Requires setting the buildFeatures.aidl to true in the build file 解决办法 修改 app 的 build.…

03_排序

03_排序 一、简单排序Comparable接口介绍需求&#xff1a; 冒泡排序排序原理&#xff1a;冒泡排序API设计&#xff1a; 选择排序排序原理&#xff1a;选择排序API设计&#xff1a;选择排序的时间复杂度分析&#xff1a; 插入排序需求&#xff1a;排序原理&#xff1a;插入排序A…