Giter Club home page Giter Club logo

chillzhuang / springblade Goto Github PK

View Code? Open in Web Editor NEW
6.5K 6.5K 1.3K 6.62 MB

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

Home Page: https://bladex.cn

License: Apache License 2.0

Dockerfile 0.42% Java 45.46% Shell 0.72% Batchfile 0.01% HTML 0.02% PLpgSQL 53.38%

springblade's Introduction

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,为工程瘦身的同时加强各模块之间的联动。
  • 极简封装了多租户底层,用更少的代码换来拓展性更强的SaaS多租户系统。
  • 借鉴OAuth2,自研多终端认证系统,可控制子系统的token权限互相隔离。
  • 借鉴Security,自研Secure模块,采用JWT做Token认证,可拓展集成Redis等细颗粒度控制方案。
  • 稳定生产了六年,经历了从 Camden -> Hoxton -> 2023 的技术架构,也经历了从fat jar -> docker -> k8s + jenkins的部署架构。
  • 项目分包明确,规范微服务的开发模式,使包与包之间的分工清晰。

架构图

核心技术栈

技术栈 版本
Java 17+
NodeJS 18+
Spring 6.1.10
Spring Boot 3.2.7
Spring Cloud 2023.0.2
Spring Cloud Alibaba 2023.0.1.0
Nacos Alibaba 2.3.2
Mybatis Plus 3.5.7

工程结构

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 

官方信息

简介 内容
官网地址 https://bladex.cn
问答社区 https://sns.bladex.cn
会员计划 SpringBlade会员计划
交流一群 477853168 (满)
交流二群 751253339 (满)
交流三群 784729540 (满)
交流四群 1034621754 (满)
交流五群 946350912 (满)
交流六群 511624269 (满)
交流七群 298061704

官方产品

简介 演示地址
BladeX企业级开发平台 https://saber3.bladex.cn
BladeX可视化数据大屏 https://data.bladex.cn
BladeX物联网开发平台 https://iot.bladex.cn

前端项目

简介 地址
前端框架Sword(基于React) https://gitee.com/smallc/Sword
前端框架Saber(基于Vue2) https://gitee.com/smallc/Saber
前端框架Saber3(基于Vue3) https://gitee.com/smallc/Saber3

后端项目

简介 地址
核心框架项目地址 https://gitee.com/smallc/blade-tool
后端Gitee地址 https://gitee.com/smallc/SpringBlade
后端Github地址 https://github.com/chillzhuang/SpringBlade
后端SpringBoot版 https://gitee.com/smallc/SpringBlade/tree/boot/

安全手册

简介 地址
Blade安全手册 https://www.kancloud.cn/smallchill/blade-safety

技术文档

简介 地址
SpringBlade开发手册一览 https://gitee.com/smallc/SpringBlade/wikis/SpringBlade开发手册
SpringBlade常见问题集锦 https://sns.bladex.cn/article-14966.html
SpringBlade基于Kuboard部署K8S https://kuboard.cn/learning/k8s-practice/spring-blade/
SpringBlade基于Rainbond部署 https://www.rainbond.com/docs/micro-service/example/blade

免费公开课

开源协议

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。

springblade's People

Contributors

chillzhuang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

springblade's Issues

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));

问题反馈流程说明

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

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

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

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

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

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

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

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

@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.

分页bug

搜索条件使用type: "datetime", searchRange:true, 选页数跳转出问题

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

下面是库存减少的代码片段,出自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);
}

如何修改用户和密码

界面没有用户配置选项。如果想要修改用户和用户密码,需要如何操作?最好是 docker image 中支持配置对应的环境变量,即用户密码能从环境变量中读取,否则部署后只要知道是该服务的用户都能登陆进行操作,安全风险很大。

[sercurity vulnerability] SQL injection

Recently, our team found a security vulnerability in the latest version of the project, which has led to the risk of SQL injection, potentially causing severe information leakage. The vulnerability lies within the method: src/main/java/org/springblade/system/user/controller/UserController.java#exportUser.
image
image

Developers, while operating the SQL statement through : the src/main/java/org/springblade/system/user/mapper/UserMapper.java#exportUsermethod, directly concatenated the input "ew" parameter to the SQL statement "SELECT id, tenant_id, account, name, real_name, email, phone, birthday, role_id, dept_id, post_id FROM blade_user ${ew.customSqlSegment}" using the " ${ew.customSqlSegment}" syntax. This means that attackers could control the "ew" parameter to execute SQL injection attacks.

使用初感

  • 看到文档介绍,好强大,都心动要自己付费了
  • 创建第一个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直接写死日志配置路径?。。。。

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

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

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

这个测试类该怎么写?

TIM图片20190614180440

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

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.