对基于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是一个 前后端分离 的项目,所以后端的服务必须先启动,在后端服务启动完成后,再启动前端的工程。
运行步骤
-
先启动redis、sentinel、mysql以及nacos注册中心
-
运行数据库脚本:依次运行数据库:ace-modules/ace-admin/db/init.sql
-
依次配置修改:ace-admin/src/main/resources/application.yml、ace- gate/src/main/resources/application.yml
-
按顺序运行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验证和权限验证
- 获取用户权限数据,并进行权限验证,然后返回结果给AccessGatewayFilter
- AccessGatewayFilter进行token验证和权限验证
-
UserAuthRestInterceptor
- 获取用户的token并解析
- 在BaseContextHandler中为会话上下文添加用户信息(ThreadLocal线程安全)
-
ServiceController
- 后台管理系统服务管理模块接口
-
UserController
- 前端异步访问 user/**,获取菜单列表和用户信息
Cloud - Platform执行过程 (后补)
数据库表之间的关系
用户授权
首先要弄清楚一下登录的流程,登录中和之后发生了什么事,那么我们打开前段登录页面,按下F12,然后点击登录,可以查看到以下几个动作:
-
登录请求http://localhost:9527/api/auth/jwt/token前,
- 到达网关gate首先经过我们的过滤器AccessGatewayFilter
- 获取请求uri,method
- 判断是否是不拦截地址
- 刚好我们发现不拦截地址中有这个配置:gate: ignore: startWith:
/auth/jwt - 所以网关过滤器直接将请求代理到ace-auth-sdk服务
- 网关ace-gate的代理以及过滤配置
- 到达网关gate首先经过我们的过滤器AccessGatewayFilter
-
输入信息点击登录,登录提交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
服务间鉴权
ace-gate启动就会调用ace-auth-sdk的AuthClientRunner进行服务鉴权
- 客户端鉴权流程:
- 这种关系在数据库中由两张表管理
- auth_client记录客户端的名称、id、code表
- auth_client_service记录服务端允许哪些客户端调用的关联关系表
总结
有些地方可能理解的也不完全对,希望有疑问的可以一起探讨,让我们一起学习一起进步。这里的总结我参考前人(直接copy)说的,,列举如下
第一点
- 新建所有需要用到的模块,基本搭建好框架
- 做好增删改查的封装、接口规范
- 全局异常捕捉封装
- 单元测试
- 通用工具类
第二点
- 决定服务的授权模式(jwt、oauth2等)
第三点
- 服务内部鉴权
- 权限控制
未完待续(随着学习的深入继续补充)
参考的文章1