IMUDGES开放平台使用说明

2019年12月20日 241点热度 0人点赞 0条评论

该使用说明已过时,新版地址:https://www.likole.com/likole-open-wiki-v1-0/

为解决IMUDGES内部系统众多,账号体系混乱的问题,所以写了个开放平台,与IMUDGES OJ账号互通(因为人最多)。

应用注册

暂不开放,请联系管理员注册。

使用流程

1.获取Authorization Code

请求地址:https://open.likole.com/oauth/authorize

请求方法:GET

请求参数:

参数是否必须含义
response_type必须授权类型,固定值“code”
client_id必须分配给应用的appid
redirect_uri必须回调地址,需与注册的地址保持一致。
state必须会原样返回,可用于防止csrf。
scope可选暂未实现

返回说明:

如果用户成功登陆并授权,会跳转到回调地址,并带上“code”(Authorization Code)和原始的“state”。

如果失败,会跳转到回调地址,并带上“error”和“error_description”。

2.通过Authorization Code获取Access Token

请求地址:https://open.likole.com/oauth/token

请求方法:POST

请求参数:

grant_type必须授权类型,固定值“authorization_code”。
client_id必须分配给应用的appid。
client_secret必须分配给应用的appkey。
code必须上一步返回的authorization code。
注意此code会在30秒内过期。
redirect_uri必须与上面一步中传入的redirect_uri保持一致。

返回说明:

如果成功返回,见下表:

access_token授权令牌,Access_Token。
expires_in该access token的有效期,单位为秒。
refresh_token授权自动续期中使用。
注:refresh_token仅一次有效

如果失败,会返回“error”和“error_description”。

3.获取用户编号

本来是想给每个应用分配不同的OpenID,但是有些应用之间得互通,为了方便,就直接返回了OJ中的用户名(唯一)。该用户名是用户身份的标识,应用可将此进行存储,便于用户下次登录时辨识其身份,或将其与用户在应用中的原有账号进行绑定。

请求地址:https://open.likole.com/resource/me

请求方法:GET POST

请求参数:access_token

返回说明:

code成功为0;出错为错误代码。
message错误描述。
data成功返回的数据。
其中的oj_id为用户唯一标识。

4.调用api

样例代码(PHP)

<?php
function send_post($url, $post_data)
{
    $postdata = http_build_query($post_data);
    $options = array(
        'http' => array(
            'method' => 'POST',
            'header' => 'Content-type:application/x-www-form-urlencoded',
            'content' => $postdata,
            'timeout' => 15 * 60
        )
    );
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    return $result;
}

header("content-type:text/html;charset=utf-8");
$app_id = "xxxxx";
$app_secret = "xxxxx";
$redirect_uri = "xxxxx";
session_start();
$error = $_REQUEST["error"];
if (!empty($error)) {
    if ($error = "access_denied") {
        die("<h3>你拒绝了登录请求,登录失败</h3><a href='$redirect_uri'>重新登录</a>");
    }
    die("<h3>error:$error</h3>");
}
$code = $_REQUEST["code"];
if (empty($code)) {
    $_SESSION['state'] = md5(uniqid(rand(), TRUE));
    header("Location:https://open.likole.com/oauth/authorize?response_type=code&client_id=$app_id&redirect_uri=" . urlencode($redirect_uri) . "&state=" . $_SESSION['state']);
}
if ($_REQUEST['state'] == $_SESSION['state']) {
    $response = send_post("https://open.likole.com/oauth/token", array(
        "grant_type" => "authorization_code",
        "client_id" => $app_id,
        "client_secret" => $app_secret,
        "redirect_uri" => urlencode($redirect_uri),
        "code" => $code
    ));
    $response = json_decode($response);
    if (!isset($response->access_token)) {
        die("<h3>error!</h3>");
    }
    $user = file_get_contents("https://open.likole.com/resource/me?access_token=" . $response->access_token);
    $user = json_decode($user);
    if (isset($user->code) && $user->code === 0) {
        $_SESSION['user_id'] = $user->data->oj_id;
        //具体处理
        header("Location:/");
    } else {
        die("<h3>登录失败,error:" . $user->message . "</h3>");
    }
} else {
    die("<h3>error:csrf detected!</h3>");
}

前后端分离注意事项

例如在vue中,可在vue-router中增加一个路由用于回调。

<script>
export default {
  name: 'AuthRedirect',
  created() {
    const query = this.$route.query
    if (query) {
      this.$store.dispatch('user/oauthLogin', query.token)
        .then(() => {
          this.$router.push({ path: '/' })
        })
    }
  },
  render: function(h) {
    return h() // avoid warning message
  }
}
</script>

当然也可以使用其他实现方式。

关于APP

APP可通过调用浏览器实现。参见 :https://tools.ietf.org/html/rfc8252

likole

人能常清静,天地悉皆归

文章评论