对基于Spring Cloud微服务化开发平台Cloud-Platform的大致理解

背景

Spring Cloud因为在两年前在上一家公司有使用过,但是不是很深入。现在是自己第三家公司,又再一次和Spring Cloud结缘(坦诚的说,第二家公司技术确实也太老了,自己也太懒惰。所以,流行了这么久的Spring Cloud自己居然还没有深入学习)。打算在业余时间进行自我学习、自我提升,虽然很难一直这么坚持笑哭

简介

关于简介,必须得抄一波咯调皮
Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API 管理等多个模块,支持多业务系统并行开发,可以作为后端服务的开发脚手架。代码简洁,架构清晰,适合学习和直接项目中使用。 核心技术采用Spring Boot 2.1.2以及Spring Cloud (Greenwich.RELEASE) 相关核心组件,采用Nacos注册和配置中心,集成流量卫兵Sentinel,前端采用vue-element-admin组件,Elastic Search自行集成。
ps:注意本文讲解是基于Cloud-Platform dev版本(2020-10-28之前的dev版本),不是最新版本!

技术选型

后端:Spring Cloud + Nacos + tk mybatis+ JWT + Hystrix + Feign + Ribbon +Zipkin

前端:vue-element-admin组件

系统架构图

架构

项目结构

ace-security

  ace-api--------------跨服务调用通用dto数据对象
    
  ace-modules--------------公共服务模块(基础系统和JWT鉴权、搜索、OSS)
  
  ace-dev-base---------------通用脚手架(基础jwtsdk、开发常用工具类)
   
  ace-gate-----------------网关负载中心
     
  ace-infrastructure--------------运维中心(监控、链路、naco注册中心、sentinel熔断流控)

后端工程启动

后端项目地址cloud-platform

须知

  • 环境须知
    • mysql一个,redis一个,sentiel一个,nacos注册中心一个
    • jdk1.8
    • IDE插件一个,lombok插件,具体百度即可
  • 项目须知
    • 因为Cloud-Platform是一个 前后端分离 的项目,所以后端的服务必须先启动,在后端服务启动完成后,再启动前端的工程。

运行步骤

  1. 先启动redis、sentinel、mysql以及nacos注册中心

  2. 运行数据库脚本:依次运行数据库:ace-modules/ace-admin/db/init.sql

  3. 依次配置修改:ace-admin/src/main/resources/application.yml、ace- gate/src/main/resources/application.yml

  4. 按顺序运行main类:AdminBootstrap(ace-admin)、GatewayServerBootstrap(ace-gate)

前端

前端项目地址: Cloud-Platform-UI-V2.

运行使用

  • git clone https://gitee.com/geek_qi/Cloud-Platform-UI-V2.git

    • npm install

    • npm start

  • node.js安装教程:nodejs.cn/download/下载msi版本安装。

  • 安装之后,命令行窗口,表示安装成功。
    版本

  • 运行启动命令
    运行

服务说明

Ace-Admin

关键类:

  • CaptchaController

    • 获取验证码,并将验证码放入缓存中,缓存的key为随机生成的uuid,缓存时间为2分钟
  • AuthController

    • 登录、刷新token、登出、校验jwt
    • 以/jwt开头,
    • 登录后返回header增加accessToken、Redis中设置在线日志和登录顺序(异步执行)
    • verify接口什么时候使用还不清楚?
    • refresh接口什么时候使用也不清楚?
  • ClientController

    • 对外暴露的接口,通过clientId+secret的获取资源信息
  • UserRest

    • AccessGatewayFilter进行token验证和权限验证
      filter
    • 获取用户权限数据,并进行权限验证,然后返回结果给AccessGatewayFilter
      返回数据
  • UserAuthRestInterceptor

    • 获取用户的token并解析
    • 在BaseContextHandler中为会话上下文添加用户信息(ThreadLocal线程安全)
  • ServiceController

    • 后台管理系统服务管理模块接口
  • UserController

    • 前端异步访问 user/**,获取菜单列表和用户信息

Cloud - Platform执行过程 (后补)

client(客户端) ace_admin(管理) ace_gate(网关) ace_auth_sdk(验证SDK) ace_common(公共类) 客户端登录 请求被网关拦截 判断用户token,获取用户信息 解析token,获取用户信息 返回解析后的用户信息 返回用户信息给网关 带着用户名,去获取用户访问权限 比较并返回访问权限信息 ajax获取用户菜单列表 这里的请求头是要带token的 返回用户菜单列表 client(客户端) ace_admin(管理) ace_gate(网关) ace_auth_sdk(验证SDK) ace_common(公共类)

数据库表之间的关系

在这里插入图片描述

用户授权

首先要弄清楚一下登录的流程,登录中和之后发生了什么事,那么我们打开前段登录页面,按下F12,然后点击登录,可以查看到以下几个动作:

  • 登录请求http://localhost:9527/api/auth/jwt/token前,

    • 到达网关gate首先经过我们的过滤器AccessGatewayFilter
      • 获取请求uri,method
      • 判断是否是不拦截地址
      • 刚好我们发现不拦截地址中有这个配置:gate: ignore: startWith:
        /auth/jwt
      • 所以网关过滤器直接将请求代理到ace-auth-sdk服务
        网关拦截
    • 网关ace-gate的代理以及过滤配置
      配置-网关
  • 输入信息点击登录,登录提交Request URL: http://localhost:8765/api/auth/jwt/token

  • 返回信息如下:

    {
        "statusCode": 200,
        "data": {
            "id": "1",
            "accessToken": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInVzZXJJZCI6IjEiLCJuYW1lIjoiTXIuQUciLCJpZCI6InRVNlZ5T1VYIiwiZXhwIjoxNjAzODc4NTY3fQ.MIVPuBiPJOG8ZkVYLI4lpX0mQaAcd6jYHkiqSLthL4s7DV3S2qMBXU00TyFLxw10quQ-7rvHmlWaPlXN-TYjmr3HpNnCboXWBVEu66ZpT-1hmxJD7OEnCxNH9kwbT_OQ1gUoJfh8m6yVc1YC9HAgS7ktqE6FF8R-nHbx0G9wZds"
        }
    }
    

    登录成功后,我们看到服务器返回了一个token,下次请求可以带着这个token一起请求

  • 接着前端又通过ajax 发送请求
    Request URL: http://localhost:8765/api/admin/user/v2/front/info
    得到的用户信息和菜单列表如下(其中有省略的部分):

    {
        "statusCode": 200,
        "data": {
            "avatarUrl": "https://api.adorable.io/avatars/85/abott@adorable.png",
            "userName": "Mr.AG",
            "userPermissions": [
                "userManager:btn_del",
                "menuManager:element",
                "menuManager:btn_add",
                "menuManager:btn_edit",
                "menuManager:btn_del"
            ],
            "accessMenus": [
                {
                    "id": 35,
                    "parentId": -1,
                    "children": [
                        {
                            "id": 37,
                            "parentId": 35,
                            "children": [
                                {
                                    "id": 36,
                                    "parentId": 37,
                                    "title": "表单设计器",
                                    "icon": "wpforms",
                                    "path": "/dev/form",
                                    "nodes": []
                                },
                                {
                                    "id": 38,
                                    "parentId": 37,
                                    "title": "代码生成器",
                                    "icon": "code-fork",
                                    "path": "/dev/code",
                                    "nodes": []
                                }
                            ],
                            "title": "开发基础配置",
                            "icon": "code",
                            "path": "/dev",
                            "nodes": [
                                {
                                    "id": 36,
                                    "parentId": 37,
                                    "title": "表单设计器",
                                    "icon": "wpforms",
                                    "path": "/dev/form",
                                    "nodes": []
                                },
                                {
                                    "id": 38,
                                    "parentId": 37,
                                    "title": "代码生成器",
                                    "icon": "code-fork",
                                    "path": "/dev/code",
                                    "nodes": []
                                }
                            ]
                        }
                    ],
                    "title": "开发管理系统",
                    "icon": "connectdevelop",
                    "path": "/dev",
                    "nodes": [
                        {
                            "id": 37,
                            "parentId": 35,
                            "title": "开发基础配置",
                            "icon": "code",
                            "path": "/dev",
                            "nodes": []
                        }
                    ]
                }
            ],
            "accessHeader": [
                {
                    "id": 13,
                    "parentId": -1,
                    "title": "权限管理系统",
                    "icon": "chrome",
                    "path": "/admin",
                    "nodes": []
                }
            ],
            "accessRoutes": [
                {
                    "id": 5,
                    "parentId": 13,
                    "children": [
                        {
                            "id": 1,
                            "parentId": 5,
                            "name": "userManager",
                            "icon": "user",
                            "path": "/admin/user",
                            "component": "userManager",
                            "componentPath": "pages/admin/user/index",
                            "meta": {
                                "cache": true,
                                "title": "用户管理"
                            },
                            "nodes": []
                        }
                    ],
                    "name": "baseManager",
                    "icon": "list",
                    "path": "/admin",
                    "component": "layoutHeaderAside",
                    "componentPath": "layout/header-aside/layout",
                    "meta": {
                        "cache": true,
                        "title": "基础配置管理"
                    },
                    "nodes": [
                        {
                            "id": 1,
                            "parentId": 5,
                            "name": "userManager",
                            "icon": "user",
                            "path": "/admin/user",
                            "component": "userManager",
                            "componentPath": "pages/admin/user/index",
                            "meta": {
                                "cache": true,
                                "title": "用户管理"
                            },
                            "nodes": []
                        }
                    ]
                }
            ],
            "accessInterfaces": [
                {
                    "path": "/admin/user/{*}",
                    "method": "DELETE"
                }
            ],
            "isAdmin": "0"
        }
    }
    

这里会带着jwt token来一起访问的,在Header中的名称是我们自己设置的,名称为:Authorization
token请求

服务间鉴权

ace-gate启动就会调用ace-auth-sdk的AuthClientRunner进行服务鉴权

  • 客户端鉴权流程:
客户端 ace_auth_sdk(验证SDK) ace_admin(管理) 初始化AuthClientRunner 通过clientId和secret 在ClientController获取pubKey 在客户端设置UserAuthConfig的参数 客户端可以通过Token获取用户信息 客户端 ace_auth_sdk(验证SDK) ace_admin(管理)
  • 这种关系在数据库中由两张表管理
    • auth_client记录客户端的名称、id、code表
    • auth_client_service记录服务端允许哪些客户端调用的关联关系表
      在这里插入图片描述

总结

有些地方可能理解的也不完全对,希望有疑问的可以一起探讨,让我们一起学习一起进步。这里的总结我参考前人(直接copy)说的,,列举如下

第一点

  • 新建所有需要用到的模块,基本搭建好框架
  • 做好增删改查的封装、接口规范
  • 全局异常捕捉封装
  • 单元测试
  • 通用工具类

第二点

  • 决定服务的授权模式(jwt、oauth2等)

第三点

  • 服务内部鉴权
  • 权限控制

未完待续(随着学习的深入继续补充)

参考的文章1


  1. 参考文章:基于Spring Cloud微服务化开发平台Cloud-Platform完整解析. ↩︎

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值