代码沙箱平台介绍【技术篇】
上面介绍了代码沙箱的使用方法,这篇文章介绍项目使用的技术细节。
技术支持
还是一如既往地是传统C/S
架构,采用前后端分离。
前端不再使用vue2
,开始拥抱vue3
了,毕竟vue3
都出了很久了,在各方面都比vue2
优秀,没有什么理由不拥抱新技术。
UI方面,也不再是Element UI
了,改用Arco Design
,没啥特殊原因,就想换换UI
。
还使用了OpenAPI Generator
,自动根据后端swagger
文档文件生成API
调用代码,节省了大量时间。
后端使用Golang
,不再是Java
了(Java
你不要再联系我啦,我怕go
会误会!),这是因为我想试一下go
的“大道至简”原则,而且go
的协程使用方式是如此地方便,而项目中我有一些地方使用了同步和并发,因此选择了go
。
web
框架使用的是Gin
,这是我看了一圈后,觉得还不错的,既没有过多的臃肿功能,功能也满足我的需求。
持久层使用的是Gorm
,因为本项目没有很复杂的数据库操作,使用它足够了。
代码沙箱核心使用的是Docker
,这是因为以我目前的实力,不敢在宿主机上直接运行用户的代码。
技术关键字:
前端 | 后端 |
---|---|
Vue3 ,Axios ,Vuex ,Vue-router ,Openapi codegen ,Typescript ,Arco-design |
Golang ,Gin ,Gorm ,Docker ,Redis ,MySQL |
架构图
+-----------------------------------------------------------------------------------------------+
| Nginx |
+-----------------------------------------------------------------------------------------------+
^ ^
| |
| |
| |
v v
+-----------------------------------------------------------------------------------------------+
| +-----------------------+ +---------------+ +-------------+ |
| | admin-service | | email-service | | qa-service | |
| +-----------------------+ +---------------+ +-------------+ |
| +-----------------------+ +---------------+ +-------------+ |
| | code-sandbox-service | | user-service | | key-service | |
| +-----------------------+ +---------------+ +-------------+ |
| |
+-----------------------------------------------------------------------------------------------+
^ ^
| |
| |
v v
+-----------------------------------------------------------------------------------------------+
| Go-docker-api |
+-----------------------------------------------------------------------------------------------+
^ ^
| |
| |
v v
+-----------------------------------------------------------------------------------------------+
| |
| +----------------+ +--------------+ +--------------+ |
| ..... | Java-container | | C-container | | Go-container | ...... |
| +----------------+ +--------------+ +--------------+ |
| |
| Docker |
+-----------------------------------------------------------------------------------------------+
登录凭证设置
登录功能使用的是JWT
,相比于Session
方式,它可以节省服务器内存资源,当然换来的代价是要花费CPU
资源去验证Token
正确性。
但是当我们使用图片验证码的时候,就有点困难了,传统的图片验证码生成过程为:
- 服务器生成一个随机字符串并存进内存中。
- 使用该随机字符串生成一个图片,图片中可能会有一些混淆内容,用于干扰机器人,并将图片返回给用户
- 用户提交表单,同时附上验证码
- 服务器根据某些
key
,去内存中获取验证码,比对正确性和时效性,然后判断验证码的有效性
好,验证码能否也用JWT
的方式?答案是可以的,这是因为JWT
中也可以存放数据,但是为了防止客户端拿到JWT
后直接解析JWT
内容后拿到验证码,我们应该使用一些加密或者取哈希的方式,将密文放进JWT
中,本项目的做法是:
- 服务器生成一个随机字符串,计算该随机字符串拼接上一个预定的字符串
KEY
后的MD5
. - 使用该随机字符串生成一个图片,图片中可能会有一些混淆内容,用于干扰机器人。
- 将
MD5
放进JWT
中,将JWT
和图片一起返回给用户 - 用户提交表单,同时附上验证码
- 服务器验证
JWT
时效性和正确性,并将用户提交的验证码拼接上一个预定的字符串,计算MD5
值,与JWT
内容比对。
由于JWT
内容是经过MD5
哈希的,只要KEY
没有泄露,用户就没法从JWT
中推导出验证码,也无法通过修改JWT
的方式提交错误的验证码。
代码沙箱核心设置
代码沙箱的核心功能是执行别人的代码,而代码执行是一个非常危险的操作,在安全领域有一个名词RCE
(Remote Code Execution)描述的是黑客通过某些手段使得受害者的服务器上面运行脚本,但是本项目功能就是运行代码,似乎和安全冲突了?实际上业务往往都是和安全冲突的,我们能做的就是尽量兼顾二者.
一个服务器的资源,不外乎CPU
,内存,硬盘,带宽,本项目是如何保障这些资源不被滥用的?
前面说过,代码沙箱核心是借助Docker
完成的,这是因为Docker
天然的隔离性,对安全十分友好,只要不是出现了逃逸漏洞,攻击者最多只能攻陷容器,而对宿主机产生的影响不大.
而Docker
除了隔离性外,容器创建时,还可指定CPU
个数和内存上限,使得容器中使用的资源是有限的。
对于硬盘,在创建容器时无法限制,但是可以通过配置Docker
的配置文件,从而限制每个容器能使用的硬盘空间上限。
对于带宽,直接限制用户不能联网,这是因为一台能远程代码执行且能联网的机器实在是太危险了,一不小心就成了别人发动DDoS
的肉鸡设备。
## 开放API
在执行代码方面,除了常规的使用前端页面提交代码外,本项目还提供使用API key
的方式提交,只不过与普通的API开放平台不同,提交的内容是加密过的,还需要使用Secrect key
对自己提交的内容签名。
为什么要这么做?一方面,加密是为了防止中间人监听攻击,只拿到了Access key
无法解密数据,而签名是防止中间人重放攻击,只拿到Access key
无法修改数据,一旦修改数据,签名内容就会对不上。
具体使用方法请参照【文档】
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!