SpringCloudAlibaba(一)---Gateway+feign+nacos+jwt完成验证登录(配置+代码)

本文示例实现以gateway作为网关代理auth和user模块,在auth和user模块间使用feign实现远程服务调用。并在gateway的全局过滤器中使用 jwt 实现登录认证。

涉及到的知识点有: gateway、nacos、openfeig、 jwt权限认证、threadlocal

调用过程图如下:
在这里插入图片描述
因配置和代码篇幅太长,分为配置篇和代码篇,本篇为配置篇,代码篇更新完会放链接在此处,可以收藏一下,有问题的话也可以发私信,看到会回。

一、引入maven依赖

(1)parent 模块 pom.xml

<properties>
        <commons-lang3.version>3.7</commons-lang3.version>
        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.18.0</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <durid.version>1.1.9</durid.version>
        <mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
        <swagger.version>2.9.2</swagger.version>
        <fastjson.version>1.2.47</fastjson.version>
        <se_jwt.version>1.0.9.RELEASE</se_jwt.version>
        <jjwt.version>0.9.0</jjwt.version>
        <pagehelper.version>1.2.5</pagehelper.version>
</properties>


<dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
      <!--   nacos发现的依赖      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos 作为配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
      <!-- mysql8 的 依赖       -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
        <!--  openfeign 依赖       -->
        <dependency>
            <!--父POM中锁定了版本信息,只需引入G,A即可 -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    <!--       mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>


<!--  dependencyManagement作为父模块 版本控制  -->
    <dependencyManagement>
     <dependencies>
        <!-- spring-cloud 相关依赖  openfeign 要用到-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--  springboot 2.2.2    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--  spring cloud alibaba 2.1.0.RELEASE    -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId> spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-starter</artifactId>
             <version>${durid.version}</version>
         </dependency>

         <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>

         <!--jwt-->
         <dependency>
             <groupId>org.springframework.security</groupId>
             <artifactId>spring-security-jwt</artifactId>
             <version>${se_jwt.version}</version>
         </dependency>
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
             <artifactId>jjwt</artifactId>
             <version>${jjwt.version}</version>
         </dependency>

         <!-- springboot 整合 pagehelper -->
         <dependency>
             <groupId>com.github.pagehelper</groupId>
             <artifactId>pagehelper-spring-boot-starter</artifactId>
             <version>${pagehelper.version}</version>
         </dependency>
     </dependencies>
    </dependencyManagement>

(2)gateway模块pom.xml (不可引入spring-starter-web 的依赖)


<dependencies>
      <!--   添加gateway的依赖-->
     <!--    springcloudgateway的内部是通过netty+webflux实现的,webflux实现和springmvc配置依赖冲突。所以gateway模块 千万不能引入 spring的web starter       -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--    用于整合 openfeign -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.9.RELEASE</version>
        </dependency>

     <!--  jwt 依赖      -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>${se_jwt.version}</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

(3)auth模块 pom.xml

<dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <artifactId>cloud-api-9002</artifactId>
        </dependency>

     <!--   <dependency>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <artifactId>cloud-common-9007</artifactId>
        </dependency> -->

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
            <!--nacos 作为配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    <!--   mysql 作为数据库连接依赖     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

        <!--jwt-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>${se_jwt.version}</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>${poi.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

(4)user模块 pom.xml

<!--        存放openfeign接口和model-->
        <dependency>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <artifactId>cloud-api-9002</artifactId>
        </dependency> 
       <!-- 该模块主要做一些工具类       -->
       <!-- <dependency>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <artifactId>cloud-common-9007</artifactId>
        </dependency> -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
            <!--nacos 作为配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    <!--   mysql 作为数据库连接依赖     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

<!--   druid 数据源  -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${durid.version}</version>
        </dependency>

        <!--jwt-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>${se_jwt.version}</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>${poi.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

(5)Api 模块的 pom.xml 配置


 <dependencies>
       <!--  <dependency>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <artifactId>cloud-common-9007</artifactId>
        </dependency>
         -->  
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos 作为配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
        <dependency>
            <!--父POM中锁定了版本信息,只需引入G,A即可 -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--        用于整合 openfeign -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

二、application/bootstrap.yml 配置

(1) Gateway 的 bootstarp.yml 配置


server:
  port: 9001
  servlet:
    context-path: /gateway

spring:
  application:
    name: cloud-gateway
  cloud:
    #gateway的配置
    gateway:
      #路由配置规则
      routes:
        - id: user_route #路由的唯一标识
          uri: http://127.0.0.1:9003 #需要转发的地址 配置了nacos 也可用 lb:服务名实现负载
          #断言规则 用于路由配置规则
          #让 http://localhost:9001/user/*** 路由到  http://localhost:9003/user/***
          #配置过滤器规则
          predicates:
            - Path=/user/**
#          filters:
#            - StripPrefix=1 #配置该参数是去掉 /user 让 http://localhost:9003/user/*** 变为 http://localhost:9003/***  我自己的服务user模块配置了servlet.context-path为user 可以不配
        - id: auth_route
          uri: http://127.0.0.1:9006 
          predicates:
           - Path=/auth/**
    #nacos的配置
    nacos:
      discovery:
        server-addr: nacos的ip:nacos的端口  #nacos 作为注册中心 如果这里配置了 nacos集群  就填写 nginx代理地址
      config:
        server-addr: nacos的ip:nacos的端口 #nacos 作为配置中心
        file-extension: yaml #指定为yaml 格式



(2) Auth 模块的 bootstarp.yml 配置

server:
  port: 9006
  servlet:
    context-path: /auth

spring:
  application:
    name: cloud-auth
  cloud:
    nacos:
      discovery:
        server-addr: nacos的ip:nacos的端口  #nacos 作为注册中心    配置nacos集群  nginx代理地址
      config:
        server-addr: nacos的ip:nacos的端口 #nacos 作为配置中心
        file-extension: yaml #指定为yaml 格式

(3) User 模块的 bootstarp.yml 配置

server:
  port: 9003
  servlet:
    context-path: /user
#配置druid作为数据源
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://数据库ip:数据库端口/数据库名
    username: 账号
    password: 密码
    
spring:
  application:
    name: cloud-user
    nacos:
      discovery:
        server-addr: nacos的ip:nacos的端口  #nacos 作为注册中心    配置nacos集群  nginx代理地址
      config:
        server-addr: nacos的ip:nacos的端口 #nacos 作为配置中心
        file-extension: yaml #指定为yaml 格式
 

(4) Api模块的bootstarp.yml 配置

server:
  port: 9002
  servlet:
    context-path: /api

#nacos sentinel 等配置
spring:
  application:
    name: cloud-api
  cloud:
    nacos:
      discovery:
        server-addr: nacos的ip:nacos的端口  #nacos 作为注册中心    配置nacos集群  nginx代理地址
      config:
        server-addr: nacos的ip:nacos的端口 #nacos 作为配置中心
        file-extension: yaml #指定为yaml 格式
        
`RuoYi-Cloud + Vue3` 是个基于 Spring Cloud Alibaba 微服务架构、前后端分离的权限管理系统,结合前端使用 Vue3 的现代化技术栈。所谓“全景预览”是指从项目结构、技术栈、模块划分、部署方式到核心功能实现的整体概览。 下面我将为你提供 `RuoYi-Cloud + Vue3` 的**完整全景预览**,包括: - 技术架构 - 项目结构说明 - 核心模块功能 - 前后端交互流程 - 部署方案 - 示例代码登录模块为例) - 扩展建议 --- ## ✅ 、技术架构图(逻辑结构) ``` +------------------+ +------------------+ | Vue3 前端系统 | <---> | Gateway 网关 | +------------------+ +------------------++----------------------------+ | 认证中心 (Auth Service) | +----------------------------++---------------+ +----------------+ +-------------+ | 系统管理服务 | | 监控服务(Monitor) | | 代码生成服务等 | | (System Service)| | (如:OSS, Job) | | (Gen Service)| +---------------+ +----------------+ +-------------+ 注册中心:Nacos 配置中心:Nacos RPC 调用:OpenFeign / Dubbo(可选) 安全认证:OAuth2 + JWT + Spring Security 网关路由:Spring Cloud Gateway 前端框架:Vue3 + Vite + Element Plus 数据库:MySQL + MyBatis-Plus 消息队列:RocketMQ / RabbitMQ(可选) 日志监控:ELK / SkyWalking ``` --- ## ✅ 二、项目结构说明(Maven 多模块) ```bash ruoyi-cloud/ ├── ruoyi-gateway/ # 网关服务 ├── ruoyi-auth/ # 认证中心(OAuth2 登录JWT签发) ├── ruoyi-system/ # 系统管理微服务(用户、角色、菜单) ├── ruoyi-monitor/ # 监控服务(在线用户、日志查看) ├── ruoyi-common/ # 公共模块(工具类、常量、DTO) │ ├── ruoyi-common-core # 核心工具 │ └── ruoyi-common-datascope # 数据权限 ├── ruoyi-api/ # 远程调用接口定义(Feign 接口) └── ruoyi-file/ # 文件服务(MinIO/OSS上传) ``` 前端项目独立: ```bash ruoyi-ui-vue3/ ├── src/ │ ├── api/ # 封装 axios 请求 │ ├── components/ # 通用组件 │ ├── layout/ # 布局组件 │ ├── router/ # 路由配置(动态路由) │ ├── store/ # Pinia 状态管理 │ ├── views/ # 页面视图 │ └── utils/ # 工具函数 ├── vite.config.js # Vite 构建配置 └── package.json ``` --- ## ✅ 三、核心功能模块 | 模块 | 功能 | |------|------| | 用户管理 | 增删改查、状态控制、导入导出 | | 角色管理 | 权限分配、数据权限设置 | | 菜单管理 | 动态菜单、按钮权限 | | 部门管理 | 树形结构展示 | | 字典管理 | 系统枚举值统维护 | | 参数设置 | 可配置项管理 | | 日志管理 | 操作日志、登录日志 | | 在线用户 | 实时会话管理(Redis 存储 token) | | 代码生成 | 自动生成功能 CRUD 前后端代码 | --- ## ✅ 四、前后端交互流程(以登录为例) ### 1. 前端 Vue3 登录请求(`login.vue`) ```vue <script setup> import { ref } from 'vue' import { loginApi } from '@/api/login' import { setToken } from '@/utils/auth' const username = ref('') const password = ref('') const handleLogin = async () => { try { const res = await loginApi({ username: username.value, password: password.value, grant_type: 'password', client_id: 'ruoyi', client_secret: '123456' }) setToken(res.access_token) // 获取用户信息 + 动态路由 window.location.href = '/index' } catch (error) { ElMessage.error('登录失败') } } </script> <template> <el-form @submit.prevent="handleLogin"> <el-input v-model="username" placeholder="用户名"/> <el-input v-model="password" type="password" placeholder="密码"/> <el-button type="primary" native-type="submit">登录</el-button> </el-form> </template> ``` > **说明**: > - 使用 `axios` 封装请求; > - 登录后将 `access_token` 存入 localStorage; > - 后续请求携带 `Authorization: Bearer xxx`。 --- ### 2. 后端认证中心 (`ruoyi-auth`) 接收登录请求 ```java @RestController @RequestMapping("/token") public class TokenController { @PostMapping("login") public ResponseEntity<OAuth2AccessToken> getToken(PasswordRequest request) { OAuth2AccessToken accessToken = authService.getToken(request); return ResponseEntity.ok(accessToken); } } ``` 其中 `authService.getToken()` 使用 Spring Security OAuth2 流程验证用户名密码,并返回 JWT token。 --- ### 3. 网关拦截与鉴权 在 `ruoyi-gateway` 中添加全局过滤器进行 token 验证: ```java @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getHeaders().getFirst("Authorization"); if (token == null || !token.startsWith("Bearer ")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } // 解析 JWT 并校验(可用 JJWT 或 Nimbus JOSE) try { Claims claims = JwtUtil.parseJWT(token.substring(7)); // 设置上下文(如 userId, username) exchange.getAttributes().put("claims", claims); } catch (Exception e) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -100; // 优先级最高 } } ``` --- ## ✅ 五、动态菜单 & 权限控制(Vue3 实现) ### 前端:根据用户权限拉取菜单并生成路由 ```js // store/user.js (Pinia) export const useUserStore = defineStore('user', { state: () => ({ userInfo: null, routes: [] }), actions: { async loadUserInfoAndRoutes() { const res = await getUserInfo() this.userInfo = res.user this.routes = generateRoutesFromPermissions(res.permissions) // 动态添加路由 this.routes.forEach(route => router.addRoute(route)) } } }) ``` ```js // utils/router.js export function generateRoutesFromPermissions(permissions) { return permissions.map(p => ({ path: p.path, name: p.name, component: () => import(`@/views/${p.component}.vue`), meta: { title: p.title, perms: p.perms } })) } ``` > 路由懒加载 + 权限指令 `v-hasPermi="'system:user:list'"` ```js // directives/hasPermi.js export default { mounted(el, binding) { const userPerms = JSON.parse(localStorage.getItem('perms') || '[]') if (!userPerms.includes(binding.value)) { el.parentNode?.removeChild(el) } } } ``` --- ## ✅ 六、部署方案 | 服务 | 部署方式 | |------|----------| | Nacos Server | Docker 单机或集群 | | RuoYi-Gateway | Spring Boot Jar | | RuoYi-Auth | Spring Boot Jar | | RuoYi-System | Spring Boot Jar | | Vue3 前端 | Nginx 静态托管 | | MySQL | Docker 容器或物理机 | | Redis | 缓存 session 和 token | **Nginx 配置示例**: ```nginx server { listen 80; server_name localhost; location / { root /usr/share/nginx/html/ruoyi-ui; index index.html; try_files $uri $uri/ /index.html; } # 代理后端服务 location /api/ { proxy_pass http://gateway:9200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` --- ## ✅ 七、扩展建议 - 使用 `SkyWalking` 做链路追踪 - 引入 `Seata` 分布式事务 - 使用 `MinIO` 替代本地文件上传 - 前端支持暗黑模式(Vue3 + CSS 变量) - 支持多租户 SaaS 模式(字段隔离 or schema 隔离) --- ## ✅ 总结 `RuoYi-Cloud + Vue3` 是套成熟的国产开源企业级中后台解决方案,具备: - 微服务解耦清晰 - 安全认证完善(OAuth2) - 前后端分离彻底 - 权限粒度精细(菜单 + 按钮 + 数据) - 可快速二次开发 适合用于中大型项目的基础平台搭建。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值