代码沙箱平台介绍【技术篇】
上面介绍了代码沙箱的使用方法,这篇文章介绍项目使用的技术细节。
技术支持
还是一如既往地是传统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无法修改数据,一旦修改数据,签名内容就会对不上。
具体使用方法请参照【文档】
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!
