微服务---gateway网关

目录

gateway作用

gateway使用

添加依赖

配置yml文件

自定义过滤器

nacos上的gateway的配置文件


我们现在知道了通过nacos注册服务,通过feign实现服务间接口的调用,那对于不同权限的用户访问同一个接口,我们怎么知道他是否具有访问的权限呢?或者我们怎么判断是否用户已经登录了呢?这些都可以通过gateway进行实现~

gateway作用

        Spring Cloud Gateway是Spring Cloud生态系统中的一员,它被设计用于处理所有微服务的入口流量。作为一个反向代理,它不仅提供了负载均衡和路由功能,还支持灵活的过滤器机制,过滤器可以在请求进入网关和离开网关时执行,用于处理各种逻辑,如身份验证、日志记录和性能监测,使得开发者能够定制和扩展其功能。

下图提供了一个关于 Spring Cloud Gateway 如何工作的高层次概述。

        客户端向 Spring Cloud Gateway 发出请求。如果Gateway处理程序映射确定一个请求与路由相匹配,它将被发送到Gateway Web处理程序。这个处理程序通过一个特定于该请求的过滤器链来运行该请求。过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和之后运行逻辑。所有的 "pre" (前)过滤器逻辑都被执行。然后发出代理请求。在代理请求发出后,"post" (后)过滤器逻辑被运行。 

gateway使用

添加依赖

 <!--nacos服务注册发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--网关gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </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>
        <!--开启Spring Cloud 应用程序启动时加载bootstrap配置文件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.4</version>
        </dependency>

配置yml文件

gateway的配置文件其实就是将所有接口配置到web服务中,然后通过具体的过滤原则来访问每个接口

    其中- Authoriza=false表示是否需要通过token验证,这个为我们自定义的一个过滤原则名称的前缀,- StripPrefix=1为在发送请求时是否需要去掉第一层路径,比如/api/user/**如果StripPrefix=1表示api需要去掉,实际访问的是/user/**接口。

自定义过滤器

 AuthorizaGatewayFilterFactory使我们自定义的一个过滤器,gateway的自定义过滤器名字是有一定要求的,即 “你想取的过滤器名字前缀+GatewayFilterFactory”,这里以我的为例,然后把前缀作为刚刚配置文件的配置进行配置

然后我们实现这个自定义的过滤器

package com.yinan.authorize;

import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
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 java.util.Arrays;
import java.util.List;


@Component
@Slf4j
@Data
@ConfigurationProperties(prefix ="exclude")
public class AuthorizaGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizaGatewayFilterFactory.Config> {

    /**
     * 需要放行的授权接口(nacos中的配置文件)
     */
    private String[] path;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 授权token
     */
    private static final String AUTHORIZE_TOKEN = "Authorization";

    /**
     *
     */
    private static final String AUTHORIZE_IP = "x-access-ip";

    /**
     * 用来标记是否需要授权校验
     */
    private static final String AUTHORIZE_RESOURCE = "x-access-resource";


    public AuthorizaGatewayFilterFactory() {
        super(Config.class);
        log.info("Loaded GatewayFilterFactory [Authorize]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }


    @Override
    public GatewayFilter apply(Config config) {
        log.info("你已经进入gateway的过滤器中了----------");
        return (exchange, chain) -> {
            if (!config.enabled) {
                return chain.filter(exchange);
            }
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders headers = request.getHeaders();
            ServerWebExchange build = null;

//            从header中获取token信息
            String token = headers.getFirst(AUTHORIZE_TOKEN);

//            获取用户IP
            String ip = headers.getFirst(AUTHORIZE_IP);
            log.info("当前访问url: " + request.getURI());
            if (token == null) {
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            log.info("请求的token为:" + token);
            log.info("请求的ip为:"+ ip);
            if (!"".equals(token)) {
                try {
                    ValueOperations<String, String> value = redisTemplate.opsForValue();
                    String userid = value.get(ip + "_user_" + "_userid_" + token);
                    System.out.println("userid:"+ userid);
                    String username = value.get(ip + "_user_" + "_username_" + token);
                    String auth=value.get(ip+"_token_"+userid);
                    if(auth==null){
                        response.setStatusCode(HttpStatus.UNAUTHORIZED);
                        return response.setComplete();
                    }
//            设置请求头
                    ServerHttpRequest host = exchange.getRequest().mutate().headers(httpHeaders -> {
                        httpHeaders.add("USER-ID", userid);
                        httpHeaders.add("USER-NAME", username);
                    }).build();
                    build = exchange.mutate().request(host).build();
//            判断是否需要接口授权校验
                    if (StringUtils.isNotBlank(headers.getFirst(AUTHORIZE_RESOURCE))) {
                        Boolean authority = getAuthority(request.getURI().toString(), userid);
                        if (authority) {
                            response.setStatusCode(HttpStatus.UNAUTHORIZED);
                            return response.setComplete();
                        }
                    }
//            黑名单校验
//                    if (checkBlackList(ip, username)) {
//                        response.setStatusCode(HttpStatus.FORBIDDEN);
//                        return response.setComplete();
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
//                    token无效
                    log.error("出现异常【{}】", e.getMessage());
                    //设置状态码
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    return response.setComplete();
                }
            }
//认证通过,将用户ID进行传递到下游服务器
            return chain.filter(build);
        };
    }

    /**
     * 校验黑名单
     * @param ip
     * @param username
     * @return
     */
//    private boolean checkBlackList(String ip, String username) {
//
//    }

    /**
     *  获取用户权限(接口权限校验)
     * @param url
     * @param userid
     * @return
     */
    private Boolean getAuthority(String url, String userid) {
        //放行接口不需要做授权校验,直接放行
        for (String path:path
             ) {
            if(url.indexOf(path)!=-1){
                return false;
            }
        }
        //获取用户权限
        String resource=redisTemplate.opsForValue().get("userPermission:"+userid);
        List<String> list= JSONArray.parseArray(resource,String.class);
        for (String res:list
             ) {
            if(url.indexOf(res)!=-1){
                return false;
            }
        }
        return true;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Config {
        /**
         * 控制是否开启认证
         */
        private boolean enabled;
    }

}

如果你看了我之前讲的nacos配置的内容,那你应该就能理解以下截图中的意思,没有了解过nacos的话建议先去看看以下文章:微服务----nacos配置及简单使用

nacos上的gateway的配置文件

management:
  # 端点检查(健康检查)
  endpoints:
    web:
      exposure:
        include: "*"
spring:
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      # 处理跨域
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods: "*"
      discovery:
        locator:
          # false为服务器名不自动匹配,true则相反
          enabled: false
          # 服务名以小写进行匹配
          lowerCaseServiceId: true
      routes:
        # web服务
        - id: service-1
          uri: lb://data-server
          predicates:
            - Path=/scriptsContent/**
          filters:
          #开启token验证
            - Authoriza=true
            - StripPrefix=0
        
        - id: service-2
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - Authoriza=false
            - StripPrefix=0

#需要放行的授权接口
exclude:
  path:
    - /system/dictionary/by
    - /system/resource/by
    - /system/role/by
    - /system/api/user/by
    - /system/black/by
    - /oss
    - /web/article/by
    - /web/code/by

pattern:
  dateformat: yyyy/MM/dd hh:mm:ss

以上就是我的具体的过滤器实现逻辑,但是需要根据你实际的项目代码逻辑对这个过滤器进行修改 。

        实现后,当前端调用你的接口时,会经过gateway网关中的过滤器看看你是否有这个权限进行访问,或者是否需需要经过登录后才能访问,如果以上都没问题,就会放行到下游过滤器继续进行检查,如果都没有问题最后就会调用到你的接口~

        以上几篇博文我们大致讲了一下微服务的搭建和使用,本人也是最近刚学会微服务,对于简单的微服务搭建你可以根据我的这几篇博文进行学习,如果版本这些没什么问题是肯定能实现的,至于这些技术较深的理解和学习如果你有兴趣可以继续进行专研学习,我们共同进步~

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

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

相关文章

Grafana:云原生时代的数据可视化与监控王者

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Grafana&#xff1a;让数据说话的魔术师》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Grafana简介 2、Grafana的重要性与影响力 …

开发体育赛事直播平台,研发技术选型与架构设计实现方案

本文将深入探讨“东莞梦幻网络科技”现成体育直播源码的技术实现方案&#xff0c;如何为用户提供流畅、互动、个性化的观赛体验。 一、技术栈选择&#xff1a;强强联合的基石1、后端开发&#xff1a;采用Java与PHP作为主要开发语言。Java以其强大的企业级应用支持&#xff0c;保…

双向冒泡法,可以只求最大最小值

int BiBubbleSort(int Arr[],int n,int maxnum){int left0,rightn-1;int i;bool notDone true;int temp;if(n<2)return -1;while(left<right&&notDone){ notDone false; //设置未发生交换标志 for(ileft;i<right;i){if(Arr[i]>Arr[i1]){//swap(Arr[…

初识指针(1)<C语言>

前言 指针是C语言中比较难的一部分&#xff0c;大部分同学对于此部分容易产生“畏难情结”&#xff0c;但是学习好这部分对C语言的深入很大的帮助&#xff0c;所以此篇主要以讲解指针基础为主。 指针概念 变量创建的本质就是在内存中申请空间&#xff0c;找到这个变量就需要地址…

tiny-Tcmalloc(高并发内存池)

项目地址&#xff08;绝对可运行&#xff09; 一. 初识高并发内存池 1、项目介绍 当前项目是实现一个高并发的内存池&#xff0c;它的原型是google的一个开源项目tcmalloc&#xff0c;tcmalloc全称Thread-Caching Malloc&#xff0c;即线程缓存的malloc&#xff0c;实现了高…

Pytorch 实现 GAN 对抗网络

GAN 对抗网络 GAN&#xff08;Generative Adversarial Network&#xff09;对抗网络指的是神经网络中包括两个子网络&#xff0c;一个用于生成信息&#xff0c;一个用于验证信息。下面的例子是生成图片的对抗网络&#xff0c;一个网络用于生成图片&#xff0c;另一个网络用于验…

Bookends for Mac:文献管理工具

Bookends for Mac&#xff0c;一款专为学术、研究和写作领域设计的文献管理工具&#xff0c;以其强大而高效的功能深受用户喜爱。这款软件支持多种文件格式&#xff0c;如PDF、DOC、RTF等&#xff0c;能够自动提取文献的关键信息&#xff0c;如作者、标题、出版社等&#xff0c…

Unity 性能优化之静态批处理(三)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、静态批处理是什么&#xff1f;二、使用步骤1.勾选Static Batching2.测试静态合批效果 三、静态合批得限制1、游戏对象处于激活状态。2、游戏对象有一…

Kannala-Brandt 鱼眼相机模型

最近在学习 ORB-SLAM3 的源代码&#xff0c;并模仿、重构了相机模型的实现 在学习的过程中发现针孔相机 (Pinhole) 与鱼眼相机 (Fisheye) 都有畸变参数&#xff0c;但是鱼眼相机无法使用 cv::undistort 函数去畸变 在对鱼眼相机的深度归一化平面进行可视化后&#xff0c;发现…

CNN实现卫星图像分类(tensorflow)

使用的数据集卫星图像有两类&#xff0c;airplane和lake&#xff0c;每个类别样本量各700张&#xff0c;大小为256*256&#xff0c;RGB三通道彩色卫星影像。搭建深度卷积神经网络&#xff0c;实现卫星影像二分类。 数据链接百度网盘地址&#xff0c;提取码: cq47 1、查看tenso…

swift微调多模态大语言模型

微调训练数据集指定方式的问题请教 Issue #813 modelscope/swift GitHubQwen1.5微调训练脚本中&#xff0c;我用到了--dataset new_data.jsonl 这个选项&#xff0c; 可以训练成功&#xff0c;但我看文档有提到--custom_train_dataset_path这个选项&#xff0c;这两个有什么…

C语言中字符串输入的3种方式

Ⅰ gets() 函数 gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间 # include <stdio.h> int main(void) {char a[256] {0};gets(a);printf("%s",a);return 0; }Ⅱ getchar() # include <stdio.h> int mai…

「 网络安全常用术语解读 」通用安全通告框架CSAF详解

1. 简介 通用安全通告框架&#xff08;Common Security Advisory Framework&#xff0c;CSAF&#xff09;通过标准化结构化机器可读安全咨询的创建和分发&#xff0c;支持漏洞管理的自动化。CSAF是OASIS公开的官方标准。开发CSAF的技术委员会包括许多公共和私营部门的技术领导…

VsCode插件 -- Power Mode

一、安装插件 1. 首先在扩展市场里搜索 Power Mode 插件&#xff0c;如下图 二、配置插件 设置 点击小齿轮 打上勾 就可以了 第二种设置方法 1. 安装完成之后&#xff0c;使用快捷键 Ctrl Shift P 打开命令面板&#xff0c;在命令行中输入 settings.json &#xff0c; 选择首…

流畅的python-学习笔记_数据结构

概念 抽象基类&#xff1a;ABC, Abstract Base Class 序列 内置序列类型 分类 可分为容器类型和扁平类型 容器类型有list&#xff0c; tuple&#xff0c; collections.deque等&#xff0c;存储元素类型可不同&#xff0c;存储的元素也是内容的引用而非内容实际占用内存 …

.排序总讲.

在这里赘叙一下我对y总前四节所讲排序的分治思想以及递归的深度理解。 就以788.逆序对 这一题来讲&#xff08;我认为这一题对于分治和递归的思想体现的淋淋尽致&#xff09;。 题目&#xff1a; 给定一个长度为 n&#x1d45b; 的整数数列&#xff0c;请你计算数列中的逆序对…

易语言IDE界面美化支持库

易语言IDE界面美化支持库 下载下来可以看到&#xff0c;是一个压缩包。 那么&#xff0c;怎么安装到易语言中呢&#xff1f; 解压之后&#xff0c;得到这两个文件。 直接将clr和lib丢到易语言安装目录中&#xff0c;这样子就安装完成了。 打开易语言&#xff0c;在支持库配置…

C#-快速剖析文件和流,并使用(持续更新)

目录 一、概述 二、文件系统 1、检查驱动器信息 2、Path 3、文件和文件夹 三、流 1、FileStream 2、StreamWriter与StreamReader 3、BinaryWriter与BinaryReader 一、概述 文件&#xff0c;具有永久存储及特定顺序的字节组成的一个有序、具有名称的集合&#xff1b; …

【系统架构师】-选择题(十三)

1、在某企业的营销管理系统设计阶段&#xff0c;属性"员工"在考勤管理子系统中被称为"员工"&#xff0c;而在档案管理子系统中被称为"职工"&#xff0c;这类冲突称为&#xff08; 命名冲突&#xff09;。 同一个实体在同系统中存在不同的命名&am…

【4087】基于小程序实现的电影票订票小程序软件

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…