代码沙箱开放API

耗时一个月开发的OJ在线判题系统,文末有项目地址,目前还在更新代码~

给代码沙箱提供开放API

直接在 controller 暴露 CodeSandbox 定义的接口:

/**
     * 执行代码
     *
     * @param executeCodeRequest
     * @return
     */
    @PostMapping("/executeCode")
    ExecuteCodeResponse executeCode(@RequestBody ExecuteCodeRequest executeCodeRequest) {
        if (executeCodeRequest == null) {
            throw new RuntimeException("请求参数为空");
        }
        return javaNativeCodeSandbox.executeCode(executeCodeRequest);
    }

OJ后台项目调用远程代码沙箱

/**
 * 远程代码沙箱:自己开发的沙箱
 */
public class RemoteCodeSandbox implements CodeSandbox {
    @Override
    public ExecutecodeResponse executeCode(ExecutecodeCodeRequest excodeCodeRequest) {
        String url = "http://localhost:8090/executeCode";
        String jsonStr = JSONUtil.toJsonStr(excodeCodeRequest);
        String responseStr = HttpUtil.createPost(url)
                .body(jsonStr)
                .execute()
                .body();
        if(StrUtil.isBlank(responseStr)){
            throw new BusinessException(ErrorCode.API_REQUEST_ERROR,"调用远程代码沙箱接口失败:" + responseStr);
        }
        return JSONUtil.toBean(responseStr, ExecutecodeResponse.class);
    }
}

调用安全性

如果将服务不做任何的权限校验,直接发到公网,是不安全的。
1)调用方与服务提供方之间约定一个字符串(最好加密)
优点:实现最简单,比较适合内部系统之间相互调用(相对可信的环境内部调用)
缺点:不够灵活,如果 key 泄漏或变更,需要重启代码
代码沙箱服务,先定义约定的字符串:

// 定义鉴权请求头和密钥
    private static final String AUTH_REQUEST_HEADER = "auth";

    private static final String AUTH_REQUEST_SECRET = "secretKey";

改造请求,从请求头中获取认证信息,并校验:

@PostMapping("/executeCode")
    ExecuteCodeResponse executeCode(@RequestBody ExecuteCodeRequest executeCodeRequest, HttpServletRequest request,
                                    HttpServletResponse response) {
        // 基本的认证
        String authHeader = request.getHeader(AUTH_REQUEST_HEADER);
        if (!AUTH_REQUEST_SECRET.equals(authHeader)) {
            response.setStatus(403);
            return null;
        }
        if (executeCodeRequest == null) {
            throw new RuntimeException("请求参数为空");
        }
        return javaNativeCodeSandbox.executeCode(executeCodeRequest);
    }

调用方,在调用时补充请求头:

  @Override
    public ExecuteCodeResponse executeCode1680129124930162690_0.5118488017228444(ExecuteCodeRequest executeCodeRequest) {
        System.out.println("远程代码沙箱");
        String1680129124930162690_0.40790531622583837 url = "http://localhost:8090/executeCode"1680129124930162690_0.9483484149140926;
        String json =1680129124930162690_0.19810350616928618 JSONUtil.toJsonStr(executeCodeRequest);
        String responseStr =1680129124930162690_0.2206213437218354 HttpUtil.createPost(url)
                .header(AUTH_REQUEST_HEADER, AUTH_REQUEST_SECRET)
                .body(json)
                .execute()
                .body();
        if (StringUtils.isBlank(responseStr)) {
            throw new1680129124930162690_0.2870843725724177 BusinessException(ErrorCode.API_REQUEST_ERROR, "executeCode remoteSandbox error, message = " + responseStr);
        }
        return1680129124930162690_0.3405605732300334 JSONUtil.toBean(responseStr, ExecuteCodeResponse.class);
    }

2)API签名认证
给允许调用的人员分配 accessKey,secretKey,然后校验这两组 key 是否匹配
在 API 开放平台中做了这些事情

项目地址

(求求大佬们赏个star~)

前端:https://github.com/IMZHEYA/yoj-frontend
后端:https://github.com/IMZHEYA/yoj-backend
代码沙箱:https://github.com/IMZHEYA/yoj-code-sandbox

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值