如果一账通实例的维护者认为使用一整个 Web 图形客户端太重了或没有必要,也可以选择只部署一账通的核心组件并利用一账通丰富的 RESTful HTTP API 来完成管理任务。本节的目的是通过两个小例子来帮助用户初步熟悉一账通的 API ,并完成一些真实的管理操作。

为了使用一账通,我们必须首先得知所要管理的一账通实例的网络地址,以及拥有一个管理员账号(默认为 admin, admin),我们不妨设其为 arkid.example.org。

参见

  • 关于如何部署 ‘client-free’ 的一账通实例,请参见 部署与配置。
  • 这里是完整的 一账通 API 文档。


例:使用 HTTPie 命令行工具进行权限管理
这个例子将会使用 HTTPie 作为命令行客户端来完成一些简单的权限管理操作。如前所述,选用 HTTPie 因其较之传统的 cURL 更加直观易用。若读者更加习惯于使用 cURL 或其他类似的命令行工具,也完全可以使用它们来完成接下来的任务。

  1. 首先,我们需要通过特定的 API POST 管理员的用户名与密码进行登录操作来得到一个 token,并在后续请求中附带这个 token 来进行特权操作。

    1. http POST https://arkid.example.org/siteapi/oneid/ucenter/login/ username=admin password=admin

    一账通将会返回与下方 JSON 数据类似的响应,其中 token 字段即为我们想要的 token

    1. {
    2. "avatar": "",
    3. "email": "",
    4. "employee_number": "",
    5. "gender": 0,
    6. "is_admin": true,
    7. "is_manager": false,
    8. "is_settled": true,
    9. "mobile": "",
    10. "name": "",
    11. "origin_verbose": "脚本添加",
    12. "perms": [
    13. "system_oneid_all",
    14. "system_ark-meta-server_all",
    15. ],
    16. "position": "",
    17. "private_email": "",
    18. "roles": [
    19. "admin",
    20. ],
    21. "token": "${token}",
    22. "user_id": 1,
    23. "username": "admin",
    24. "uuid": "${uuid}"
    25. }
  2. 我们可以通过列出所有的用户来找到我们想为其添加权限的那一个,并记下它的 username 字段,不妨设其为 user1。将 token 置于请求头中,形如 Authorization: Token ${token} 即可以管理员身份使用所有的 API。由于结果可能会很长。此处及以后将不一一展示服务器的响应。

    1. http GET https://arkid.example.org/siteapi/oneid/user/ Authorization:'Token ${token}'
  3. 类似的,我们可以找到该用户想要访问的那个第三方应用,然后记下它的 access_perm 中我们想为其赋予的权限的 uid 字段,设其为 app_app1_access。如果不止一个,设另一个为 app_app2_access

    1. http GET https://arkid.example.org/siteapi/oneid/app/ Authorization:'Token ${token}'
  4. 为了方便,我们可以将我们想要为用户添加的权限写成独立的 JSON,记为 perm.json。其中 status 字段的取值 {-1, 0, 1} 分别代表黑名单,从上级继承与白名单。

    1. {
    2. "perm_statuses":
    3. [
    4. { "uid" : "app_app1_access", "status" : 1 },
    5. { "uid" : "app_app2_access", "status" : 1 }
    6. ]
    7. }
  5. 现在我们就可以为 user1 添加访问应用的权限了。如果把此处的 PATCH 方法改为 GET,即可列出该用户所有的权限状态。

    1. http PATCH http://arkid.example.org/siteapi/oneid/perm/user/user1/ < perm.json Authorization:'Token ${token}'

    例:使用 Python 脚本进行第三方应用接入

    这个例子将会使用经典的 Python HTTP 客户端库 requests 来实现简单的第三方应用接入配置,如果读者对 Python 语言或 requests 不甚熟悉,也可以换用任何自己喜欢的语言来完成这个小例子。
    参见

  1. 我们首先导入 requests 包。如果读者的 Python 环境中没有 requests,需要先自行安装。

    1. import requests
  2. 请根据当前一账通实例的网络配置自行填写请求的目标 URL。

    1. prefix = 'https://arkid.example.org'
  3. 和上一小节一样,我们向登录 API 发送管理员的用户名与密码来得到 token。这段代码使用了装饰器,以使得我们不必手动完成大量「先将 token 放进 headers 里,然后再发送请求」之类无聊的操作。

    1. def login(username, password):
    2. rsp = requests.post(f'{prefix}/siteapi/oneid/ucenter/login/', \
    3. json={'username': username, 'password': password})
    4. token = rsp.json()['token']
    5. def withuser(method):
    6. def wrap(*args, **kwargs):
    7. if 'headers' not in kwargs:
    8. kwargs['headers'] = { 'AUTHORIZATION': f'Token {token}' }
    9. else:
    10. kwargs['headers']['AUTHORIZATION'] = f'Token {token}'
    11. return method(*args, **kwargs)
    12. return wrap
    13. return withuser
    14. @login('admin', 'admin')
    15. def post(*args, **kwargs):
    16. return requests.post(*args, **kwargs)
  4. 然后我们通过向 /siteapi/oneid/app/ POST 一个包含该应用的创建信息的 JSON 对象来创建一个应用,其中应用的名称是唯一的必选项。

    1. def create_app(name, **kwargs):
    2. app = { 'name': name }
    3. # more configuration stuffs
    4. return post(f'{prefix}/siteapi/oneid/app/', json=app)
  5. 首先,一账通需要请求者指定一个鉴权协议的列表,先将它置空。

    1. auth_protocols = []
  6. 使用 LDAP 或 HTTP 鉴权协议不需要配置任何参数,所以我们将 ldap_apphttp_app 都置空。

    1. if 'ldap' in kwargs:
    2. app['ldap_app'] = {}
    3. auth_protocols.append('LDAP')
    4. if 'http' in kwargs:
    5. app['http_app'] = {}
    6. auth_protocols.append('HTTP')
  7. 使用 OAuth2.0 则需要用户指定一些配置,见下文。

    1. if 'oauth' in kwargs:
    2. app['oauth_app'] = kwargs['oauth']
    3. auth_protocols.append('OAuth2.0')
  8. 应用备注与跳转链接同样是能够配置的可选项。

    1. if 'remark' in kwargs:
    2. app['remark'] = kwargs['remark']
    3. if 'index' in kwargs:
    4. app['index'] = kwargs['index']
  9. 虽然不指定鉴权协议依然可以指定一个应用,但我们不希望创建这种毫无意义的空应用。

    1. if not auth_protocols:
    2. raise '至少指定一个鉴权协议!'
    3. else:
    4. app['auth_protocols'] = auth_protocols
  10. 现在我们可以真正创建一个应用了。oauth 中各项参数的具体含义参见 OAuth2.0 一节,其中 redirect_uris 为必选项。 ``` oauth = { ‘redirect_uris’: ‘your_redirection_endpoint’, ‘client_type’: ‘public’, ‘authorization_grant_type’: ‘implicit’ } app = create_app(‘your_app_name’, remark=’your_app_remark’, index=’your_app_index’, oauth=oauth)

print(app.text)

  1. 11. 运行这个程序,屏幕上打印出来的结果即为新添加的第三方应用配置接入所必须的信息,关于第三方应用自身如何利用这些信息完成鉴权,同样请参见 [OAuth2.0](https://docs.arkid.longguikeji.com/tutorial.html#oauth2-0) 一节。

{ “app_id”:1, “uid”:”yourappname”, “name”:”your_app_name”, “index”:”your_app_index”, “logo”:””, “remark”:”your_app_remark”, “oauth_app”:{ “client_id”:”${client_id}”, “client_secret”:”${client_secret}”, “redirect_uris”:”your_redirection_endpoint”, “client_type”:”public”, “authorization_grant_type”:”implicit”, “more_detail”:[ { “name”:”认证地址”, “key”:”auth_url”, “value”:”{$prefix}/oauth/authorize/“ }, { “name”:”获取token地址”, “key”:”token_url”, “value”:”{$prefix}/oauth/token/“ }, { “name”:”身份信息地址”, “key”:”profile_url”, “value”:”{$prefix}/oauth/userinfo/“ } ] }, “ldap_app”:null, “http_app”:null, “allow_any_user”:false, “auth_protocols”:[ “OAuth 2.0” ] }

  1. 组织完整的该程序 Python 源代码如下,建议读者将它直接复制到本地作为脚手架来实现读者感兴趣的其他功能。

import requests

prefix = ‘https://arkid.example.org

def login(username, password): rsp = requests.post(f’{prefix}/siteapi/oneid/ucenter/login/‘, \ json={‘username’: username, ‘password’: password}) token = rsp.json()[‘token’]

  1. def withuser(method):
  2. def wrap(*args, **kwargs):
  3. if 'headers' not in kwargs:
  4. kwargs['headers'] = { 'AUTHORIZATION': f'Token {token}' }
  5. else:
  6. kwargs['headers']['AUTHORIZATION'] = f'Token {token}'
  7. return method(*args, **kwargs)
  8. return wrap
  9. return withuser

@login(‘admin’, ‘admin’) def post(args, **kwargs): return requests.post(args, **kwargs)

def create_app(name, **kwargs): auth_protocols = [] app = { ‘name’: name }

  1. if 'remark' in kwargs:
  2. app['remark'] = kwargs['remark']
  3. if 'index' in kwargs:
  4. app['index'] = kwargs['index']
  5. if 'ldap' in kwargs:
  6. app['ldap_app'] = {}
  7. auth_protocols.append('LDAP')
  8. if 'http' in kwargs:
  9. app['http_app'] = {}
  10. auth_protocols.append('HTTP')
  11. if 'oauth' in kwargs:
  12. app['oauth_app'] = kwargs['oauth']
  13. auth_protocols.append('OAuth2.0')
  14. if not auth_protocols:
  15. raise '至少指定一个验证协议!'
  16. else:
  17. app['auth_protocols'] = auth_protocols
  18. return post(f'{prefix}/siteapi/oneid/app/', json=app)

oauth = { ‘redirect_uris’: ‘your_redirection_endpoint’, ‘client_type’: ‘public’, ‘authorization_grant_type’: ‘implicit’ } app = create_app(‘your_app_name’, remark=’your_app_remark’, index=’your_app_index’, oauth=oauth)

print(app.text) ```

1
在 HTTPie 中,不加任何命令行选项则随后的键值会以 JSON 格式发送给服务器,在 POST 操作之前加上 -f 指令将会命令 HTTPie 把这些键值以 HTTP 表单格式发送给服务器。一账通的很多 API 同时接受这两种格式的数据。