前言

RustDesk 是一个强大的开源远程桌面软件,是中国开发者的作品,它使用 Rust 编程语言构建,提供安全、高效、跨平台的远程访问体验。可以说是目前全球最火的开源远程桌面软件了,GitHub 收藏数量达到了惊人的 92k!

教程功能

NaN. 简单介绍 RustDesk ,对 RustDesk 原理进行简单说明

NaN. 提供 linux 原生安装和 docker 安装两种方式自建 RustDesk 服务器

NaN. 第三方开源 web-api 服务(RustDesk 开源版本没有权限用户相关管理权限控制,pro 版本才有)

NaN. 如何发布 RustDesk 服务端(主要为开放端口说明)

NaN. 客户端简单使用 RustDesk

视频比较细,时长较长,已经分段完成,各位小伙伴可以选择分段观看。

TeamViewerToDesk向日葵等专有远程访问解决方案相比,RustDesk 作为一个开源软件,提供了几个显著的优势:

NaN. RustDesk 完全免费使用,没有任何隐藏费用或订阅计划。

NaN. 由于其开源特性,RustDesk 的代码是透明的,可以由社区审计,从而提供更高的安全性和可信度。

NaN. 由于 RustDesk 允许自建服务器,隐私性更高

NaN. RustDesk 自建服务器硬件需求非常低官方说法如下:

1
2
硬件要求非常低;基本云服务器的最低配置就足够了,CPU和内存要求极低。您也可以使用树莓派或类似设备。关于网络规模,如果TCP打洞直连失败,将消耗中继流量。中继连接的流量根据分辨率设置和屏幕更新在30 K/s到3 M/s(1920x1080屏幕)之间。如果仅用于办公需求,流量约为100 K/s。

由于被诈骗分子频繁使用,该项目现已暂停国内服务。即国内无法通过公共服务器连接

技术架构对比

维度

TeamViewer

RustDesk

传输协议

私有协议(优化带宽和延迟)

WebRTC + 自定义协议(依赖 P2P/UDP 打洞)

中继服务器

全球分布式商业服务器(强制中转)

可选自建中继服务器(开源实现)

连接方式

优先 P2P,失败时自动中转

强制尝试 P2P,失败后走自建 / 官方中继

代码可控性

闭源

完全开源(MIT 许可)

功能差异对比

功能

TeamViewer

RustDesk

多平台支持

✔️ (Win/macOS/Linux/iOS/Android/Web)

✔️ (全平台 + 浏览器客户端)

多显示器切换

✔️ (无缝切换)

✔️

文件传输

✔️ (拖拽 / 管理界面)

✔️ (基础拖拽)

会议功能

✔️ (最多 300 人,企业版)

❌ (仅 1 对 1 控制)

远程打印

✔️ (虚拟驱动)

无人值守访问

✔️ (设备分组 / 批量部署)

✔️ (需手动设置密码)

命令行控制

✔️ (TV CLI)

✔️ (命令行参数)

移动设备控制

✔️ (Android/iOS 反向控制)

✔️ (Android/iOS 反向控制)

RustDesk 架构概述

RustDesk 采用了经典的客户端 - 服务器模型,其中涉及三个主要组件:RustDesk 客户端、RustDesk 服务器和 ID Server。

NaN. 客户端 - 服务器模型

在 RustDesk 的架构中,客户端是运行在用户设备 (如笔记本电脑、平板电脑或智能手机) 上的应用程序。它提供了一个图形界面,允许用户发起远程访问请求并与远程计算机进行交互。另一方面,服务器组件运行在要远程访问的目标计算机上。它负责监听来自客户端的连接请求,并在建立连接后向客户端发送屏幕更新和接收输入事件。

NaN. ID Server 的角色

ID Server 在 RustDesk 的生态系统中扮演着重要的角色。它的主要职责是促进客户端和服务器之间的初始连接建立。**当 RustDesk 服务器启动时,它会连接到 ID Server 并注册自己,提供如服务器 ID 和公网 IP 地址等信息**。类似地,当客户端想要连接到特定的 RustDesk 服务器时,它会向 ID Server 查询目标服务器的连接信息。

**ID Server 维护了一个已注册的 RustDesk 服务器目录,并充当客户端和服务器之间的中介,帮助它们建立直接的点对点 (P2P) 连接**。一旦客户端从 ID Server 获得了服务器的连接信息,它就可以尝试直接连接到服务器,而无需进一步通过 ID Server 中继数据。

NaN. Relay Server 的角色

在某些网络环境下,RustDesk 客户端和服务器可能**无法直接建立 P2P 连接**,例如当它们位于 NAT (网络地址转换) 或防火墙后时。为了克服这一挑战,RustDesk 引入了 Relay Server。

**如果客户端无法直接连接到服务器,它会向 ID Server 请求一个 Relay Server。然后,客户端和服务器都连接到指定的 Relay Server,并通过它来中继所有的网络通信**。Relay Server 在这种情况下充当客户端和服务器之间的桥梁,转发来自一方的数据包到另一方。

值得注意的是,即使通过 Relay Server 进行通信,RustDesk 也会维护端到端加密,确保中继服务器无法访问明文数据。Relay Server 只是盲目地转发加密的数据包,而不能查看或修改其内容。

RustDesk 部署教程

linux 原生部署

服务器配置说明:

配置项

参数

cpu

1C

内存

1G

系统

Ubuntu 24.04 任意 linux 系统

下载 Rustdesk Server

方法 2 直接前往官方页面下载

https://github.com/rustdesk/rustdesk-server/releases

方法 3 服务器直接或者代理下载

docker github 代理地址:https://www.cnproxy.top/

使用 githuab 代理或者直接下载

1
2
3
wget https://ghproxy.cnproxy.top/https://github.com/rustdesk/rustdesk-se
rver/releases/download/1.1.14/rustdesk-server-linux-amd64.zip

解压 Rustdesk Server

1
2
3
4
apt install unzip

unzip rustdesk-server-linux-amd64.zip

解压完成后会出现 hbbr,hbbs,rustdesk-utils 三个文件

hbbr

  • hbbr是 RustDesk Relay Server,即 RustDesk 中继服务器,当客户端之间无法直接建立 P2P 连接时,会通过hbbr中继服务器进行数据传输hbbr允许无法直接建立 P2P 连接的客户端通过中继服务器进行通信。

hbbs

  • hbbs代表 RustDesk ID / Rendezvous Server,即 RustDesk ID 注册服务器。它用于分配和注册 ID,并且是 RustDesk 的中介服务器(Broker Server),用于管理和协调客户端连接。hbbs帮助客户端找到并建立 P2P 连接,负责维护客户端的在线状态,并处理连接请求。当客户端 A 希望连接客户端 B 时,它会向hbbs发送请求,hbbs会帮助它们建立连接。

rustdesk-utils

  • rustdesk-utils是 RustDesk 的命令行工具,提供了一些管理和操作 RustDesk 服务器端的工具和命令。

配置系统服务且加入开机自启动

执行 vim hbbr.service 配置系统级服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=RustDesk Relay Server
After=network.target

[Service]
Type=simple
ExecStart=/opt/rustdesk/hbbr
Restart=on-failure
WorkingDirectory=/opt/rustdesk

[Install]
WantedBy=multi-user.target


执行 vim hbbs.service 配置系统级服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=RustDesk Relay Server
After=network.target

[Service]
Type=simple
ExecStart=/opt/rustdesk/hbbs
Restart=on-failure
WorkingDirectory=/opt/rustdesk

[Install]
WantedBy=multi-user.target


将服务添加到系统服务,且加入开机自启动

1
2
3
4
5
6
7
8
9
10
//将当前路径服务以软连接加入系统服务中
ln -s /opt/rustdesk/hbbr.service /etc/systemd/system/
ln -s /opt/rustdesk/hbbs.service /etc/systemd/system/
//重载服务
systemctl daemon-reload
//启动并且加入开机自启动

systemctl enable --now hbbs.service
systemctl enable --now hbbr.service

总结
  1. 解压完成后 hbbr 与 hbbs 可以移动位置,但是两个文件需放在同一目录中。

  2. 首次需要先启动 hbbs 在启动 hbbr

docker 部署教程

安装 docker

见本站 docker 安装教程 https://halo.blog360.sbs/archives/dockeran-zhuang-jiao-cheng

运行容器

docker 直接运行
1
2
3
4
5
docker run --restart=always  --name hbbs  -v /opt/rustdesk:/root -td --net=host rustdesk/rustdesk-server  hbbs  -r [服务器公网IP或域名]  


docker run  --restart=always --name hbbr   -v /opt/rustdesk:/root -td  --net=host rustdesk/rustdesk-server hbbr

docker compose 运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
version: '3'

networks:
rustdesk-net:
  external: false

services:
hbbs:
  container_name: hbbs
  ports:
     - 21115:21115
     - 21116:21116
     - 21116:21116/udp
     - 21118:21118
  image: rustdesk/rustdesk-server:latest
  command: hbbs -r rustdesk.example.com:21117 # 公网ip或者域名,为中继连接节点
  volumes:
     - ./data:/root
  networks:
     - rustdesk-net
  depends_on:
     - hbbr
   restart: unless-stopped

hbbr:
  container_name: hbbr
  ports:
     - 21117:21117
     - 21119:21119
  image: rustdesk/rustdesk-server:latest
  command: hbbr
  volumes:
     - ./data:/root
  networks:
     - rustdesk-net
   restart: unless-stopped

总结

  1. 注意配置公网访问中继节点

rustdesk-web-API-server 部署

首先我们为什么要部署 rustdesk-API-server,我们需要指定 rustdesk 开源版本与 pro 版本的区别,其核心区别主要有下:

功能

开源自托管版

Pro 自托管版

Web 管理控制台

❌ 无

✅ 完整图形化界面(设备 / 用户 / 权限管理)

API 接口

❌ 无

✅ RESTful API(自动化集成)

审计日志

❌ 仅基础连接日志

✅ 完整操作审计(登录 / 会话 / 文件传输)

设备分组 / 标签

❌ 手动管理

✅ 可视化批量管理

企业级安全

❌ 基础密码验证

✅ TOTP 两步验证 (2FA)

会议功能

❌ 仅一对一连接

✅ 支持多人会议(≤10 人)

安卓隐私黑屏

❌ 无

✅ 被控时屏幕自动黑屏

商业授权

❌ AGPLv3 (有传染性)

✅ 商业许可(规避开源风险)

官方技术支持

❌ 仅社区支持

✅ 订阅用户专属支持

对应企业而言,前五条还是比较重要的,而 pro 版本的订阅价格还比较贵,我们可以通过自行部署其他第三方 rustdesk-web-API 来解决,当然第三方肯定无法和官方的 pro 比较,如果权限要求比较细也可以购买 pro 版本支持一下

那么我们本次部署所使用的第三方 rustdesk-web-API 可以提供哪些功能呢?基本如下

功能

详情

Web 管理控制台

提供了一个完整图形化界面(设备 / 用户 / 权限管理)

API 接口

RESTful API 并且提供了 swagger 接口,可以自行定制开发

设备分组 / 标签

可视化批量管理

安全提升

可强制要求登录后才允许使用远程

项目地址:https://github.com/lejianwen/rustdesk-api

安装 docker

见本站 docker 安装教程

docker compose 运行

添加 docker-compose.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
version: '3'  # 必须声明版本(推荐 ≥3.5)

services:
rustdesk:
  image: lejianwen/rustdesk-server-s6:latest
  container_name: rustdesk-server
  ports:
    - "21114:21114"    # 注意:所有端口必须加引号(YAML规范)
    - "21115:21115"
    - "21116:21116"    # TCP端口
    - "21116:21116/udp" # UDP端口(无需重复定义TCP)
    - "21117:21117"
    - "21118:21118"
    - "21119:21119"
  environment:
    - RELAY=rustdesk.domain.com:21117 # 默认的中继服务器
    - ENCRYPTED_ONLY=1
    - MUST_LOGIN=Y  # 是否强制登陆才运行使用
    - TZ=Asia/Shanghai # 时区
    # - RUSTDESK_API_GORM_TYPE=mysql
    # - RUSTDESK_API_MYSQL_USERNAME=root
    # - RUSTDESK_API_MYSQL_PASSWORD=123456
    # - RUSTDESK_API_MYSQL_ADDR=192.168.1.1
    # - RUSTDESK_API_MYSQL_DBNAME=rustdesk_db
    - RUSTDESK_API_APP_SHOW_SWAGGER=0 # 是否启用swagger
    - RUSTDESK_API_RUSTDESK_KEY=1222112= #jwt key
    - RUSTDESK_API_RUSTDESK_API_SERVER=https:
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=rustdesk.domain.com:21117
- RUSTDESK_API_RUSTDESK_ID_SERVER=rustdesk.domain.com:21116
  volumes:
    - ./data:/data
    - ./data/api:/app/data #将数据库挂载 sqlite 数据库文件挂载 为mysql时可以不配置
  restart: unless-stopped
  networks:
    - rustdesk-net

networks:  # 顶级配置(顶格书写)
rustdesk-net:
  driver: bridge

完整参数配置

变量名

说明

示例

TZ

时区

Asia/Shanghai

RUSTDESK_API_LANG

语言

en,zh-CN

RUSTDESK_API_APP_WEB_CLIENT

是否启用 web-client; 1: 启用, 0: 不启用; 默认启用

1

RUSTDESK_API_APP_REGISTER

是否开启注册; true, false 默认false

false

RUSTDESK_API_APP_SHOW_SWAGGER

是否可见 swagger 文档;1显示,0不显示,默认0不显示

1

RUSTDESK_API_APP_TOKEN_EXPIRE

token 有效时长

168h

RUSTDESK_API_APP_DISABLE_PWD_LOGIN

是否禁用密码登录; true, false 默认false

false

RUSTDESK_API_APP_REGISTER_STATUS

注册用户默认状态; 1 启用,2 禁用, 默认 1

1

RUSTDESK_API_APP_CAPTCHA_THRESHOLD

验证码触发次数; -1 不启用, 0 一直启用, >0 登录错误次数后启用 ; 默认 3

3

RUSTDESK_API_APP_BAN_THRESHOLD

封禁 IP 触发次数; 0 不启用, >0 登录错误次数后封禁 IP; 默认 0

0

-----ADMIN 配置 -----

----------

----------

RUSTDESK_API_ADMIN_TITLE

后台标题

RustDesk Api Admin

RUSTDESK_API_ADMIN_HELLO

后台欢迎语,可以使用html

RUSTDESK_API_ADMIN_HELLO_FILE

后台欢迎语文件,如果内容多,使用文件更方便。 会覆盖RUSTDESK_API_ADMIN_HELLO

./conf/admin/hello.html

-----GIN 配置 -----

----------

----------

RUSTDESK_API_GIN_TRUST_PROXY

信任的代理 IP 列表,以,分割,默认信任所有

192.168.1.2,192.168.1.3

-----GORM 配置 -----

----------

---------------------------

RUSTDESK_API_GORM_TYPE

数据库类型 sqlite 或者 mysql,默认 sqlite

sqlite

RUSTDESK_API_GORM_MAX_IDLE_CONNS

数据库最大空闲连接数

10

RUSTDESK_API_GORM_MAX_OPEN_CONNS

数据库最大打开连接数

100

RUSTDESK_API_RUSTDESK_PERSONAL

是否启用个人版 API, 1: 启用, 0: 不启用; 默认启用

1

-----MYSQL 配置 -----

----------

----------

RUSTDESK_API_MYSQL_USERNAME

mysql 用户名

root

RUSTDESK_API_MYSQL_PASSWORD

mysql 密码

111111

RUSTDESK_API_MYSQL_ADDR

mysql 地址

192.168.1.66:3306

RUSTDESK_API_MYSQL_DBNAME

mysql 数据库名

rustdesk

-----RUSTDESK 配置 -----

----------

----------

RUSTDESK_API_RUSTDESK_ID_SERVER

Rustdesk 的 id 服务器地址

192.168.1.66:21116

RUSTDESK_API_RUSTDESK_RELAY_SERVER

Rustdesk 的 relay 服务器地址

192.168.1.66:21117

RUSTDESK_API_RUSTDESK_API_SERVER

Rustdesk 的 api 服务器地址

http://192.168.1.66:21114

RUSTDESK_API_RUSTDESK_KEY

Rustdesk 的 key

123456789

RUSTDESK_API_RUSTDESK_KEY_FILE

Rustdesk 存放 key 的文件

./conf/data/id_ed25519.pub

RUSTDESK_API_RUSTDESK_WEBCLIENT MAGICQUERYONLINE

Web client v2 中是否启用新的在线状态查询方法; 1: 启用,0: 不启用, 默认不启用

0

RUSTDESK_API_RUSTDESK_WS_HOST

自定义 Websocket Host

wss://192.168.1.123:1234

----PROXY 配置 -----

----------

----------

RUSTDESK_API_PROXY_ENABLE

是否启用代理:false, true

false

RUSTDESK_API_PROXY_HOST

代理地址

http://127.0.0.1:1080

----JWT 配置 ----

--------

--------

RUSTDESK_API_JWT_KEY

自定义 JWT KEY, 为空则不启用 JWT 如果没使用lejianwen/rustdesk-server中的MUST_LOGIN,建议设置为空

RUSTDESK_API_JWT_EXPIRE_DURATION

JWT 有效时间

168h

查看密码

执行

1
2
docker logs -f docker容器ID

查看密码

总结

  1. 注意这个服务包已经包含了 hbbr 与 hbbs,可以不用再部署了。

  2. 默认超管密码将会在容器日志中输出。

  3. 默认容器已经禁用了注册功能。

RustDesk 发布教程

在发布之前,我们需要了解 rustdesk 各个端口的作用:

了解端口,确认发布端口

hbbs 服务所需端口

协议

端口号

说明

TCP

21114

用于 Web 控制台(可选)

TCP

21115

用于 NAT 类型测试

TCP/UDP

21116

必须同时启用 TCP 和 UDP,用于 ID 注册、心跳服务(UDP)以及 TCP 打洞、连接服务(TCP)

TCP

21118

用于支持 Web 客户端(可选)

hbbr 服务所需端口

协议

端口号

说明

TCP

21117

用于中继服务

TCP

21119

用于支持 Web 客户端(可选)

那么可以根据一下需求来

RustDesk 官方开源版本

端口

是否必须

21116 tcp/udp

21117 tcp

建议开放,用于在 p2p 失败后中继

21115 tcp

建议不开放

rustdesk-web-API-server 第三方带服务版本

端口

是否必须

21116 tcp/udp

21114(443 or 80) tcp

开放 将 web 使用 443 或者 80 发布

21117 tcp

建议开放,用于在 p2p 失败后中继

21115 tcp

建议不开放

21119 tcp

建议不开放

21118

建议不开放

使用 nginx 代理发布端口

非 web 端口 nginx stream 发布 ·

NaN. 修改 nignx 配置文件,设置 stream 模块

1
2
3
4
5
6
7
8
9
10
11
    stream {
  include /etc/nginx/stream.d/*;
}



​ ```

NaN. 添加 stream 代理端口


server { listen 21116; proxy_pass 172.30.0.2:21116; proxy_connect_timeout 5s; }

# UDP端口代理(P2P打洞)
server {
    listen 21116 udp reuseport;
    proxy_pass 172.30.0.2:21116;
    proxy_timeout 3s;
}


server {
listen 21117;
proxy_pass 172.30.0.2:21117;
}

1
2
3
4
5

**web 端口发布**

在 / etc/nginx/sites-available 添加新域名配置文件,**_vim 你的域名_**

server {

listen 80;
server_name test.blog360.sbs;


location / {
client_max_body_size 50m;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://172.30.0.2:21114/;

            index index.html index.htm A1-index.html;


}


}

1
2
3

建立软连接

ln -s /etc/nginx/sites-available/你的域名 /etc/nginx/sites-enabled/你的域名

1
2
3
4
5

**web 端口申请免费证书(ssl 证书可选)**

**安装 Certbot 工具**

sudo apt update
sudo apt install certbot python3-certbot-nginx

sudo yum install epel-release
sudo yum install certbot python3-certbot-nginx

1
2
3

**申请 ssl 证书(nginx)**

sudo certbot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

* 替换 `your-domain.com` 为你的域名

### 总结

1. 注意 stream 与 http 同级。

2. 发布尽量使用标准端口,若 **rustdesk-web-API-server 使用非标端口注意启动容器配置**

**RustDesk 使用教程**
-----------------

### **RustDesk 开源社区版本使用**

1. 打开设置

![](https://halo.blog360.sbs/upload/image-20250711215759378-fEWe.png)

2. 配置网络

![](https://qt.qiongzhou.eu.org/webp/image-20250711215832375.png)

3. 配置对应的 id,中继服务器和 key

![](https://qt.qiongzhou.eu.org/webp/image-20250711215914409.png)

**key 的配置在**

1. **服务器 docker logs -f 容器 id 日志中查看**

2 **在服务器安装,目录查看一个为 id_ed------.pub 文件**

![](https://qt.qiongzhou.eu.org/webp/image-20250711220247948.png)

完成配置后,回到主页,显示**就绪**即可正常使用

![](https://qt.qiongzhou.eu.org/webp/image-20250711220337412.png)

### **pro 版本或者 rustdesk-web-API-server 版本**

#### **swagger 使用**

在配置启用 swagger 后,打开

1. 后台文档 `/admin/swagger/index.html`

2. PC 端文档 `/swagger/index.html`

即可进入对应 swagger 文档

![](https://qt.qiongzhou.eu.org/webp/image-20250711220751098.png)

#### **用户初始化**

未开放注册,若用户初始用户过多,可以通过调用 api 方式添加用户,这里提供一个 **Java 同步启用微信用户**的方法

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.util.HashMap;
import java.util.Map;

public class WeComUserSync {

public static final String QY_HOST = "企业微信url路径";
public static final String QY_CORP_ID = "企业id";
public static final String QY_CORP_SECRET = "企业微信密钥";


public static final String RUST_DESK_HOST = “http://192.168.73.129:21114/api“;
public static final String RUST_DESK_TOKEN = “430b712ba7ef99da742c9c15bc5ae4c0”;


public static void syncUsers() {
String weComAccessToken = getWeComAccessToken();

    JSONArray wecomUsers = getWeComUsers(weComAccessToken);

    for (Object user : wecomUsers) {
        JSONObject wecomUser = (JSONObject) user;
        JSONObject targetUser = convertToTargetFormat(wecomUser);
        createUser(targetUser);
    }
}


public static String getWeComAccessToken() {

    Map<String, Object> params = new HashMap<>();
    params.put("corpid", QY_CORP_ID);
    params.put("corpsecret", QY_CORP_SECRET);

    HttpResponse response = HttpRequest.get(QY_HOST +"/cgi-bin/gettoken")
            .form(params)
            .execute();

    JSONObject result = JSONUtil.parseObj(response.body());

    if (result.getInt("errcode") != 0) {
        throw new RuntimeException("获取access_token失败: " + result.getStr("errmsg"));
    }


return result.getStr(“access_token”);
}


public static JSONArray getWeComUsers(String weComAccessToken) {

String departmentId = “1”;
String fetchChild = “1”;

    String url = String.format(QY_HOST +"/cgi-bin/user/list?access_token=%s&department_id=%s&fetch_child=%s",
            weComAccessToken, departmentId, fetchChild);


    HttpResponse response = HttpRequest.get(url).execute();
    String body = response.body();
    JSONObject result = JSONUtil.parseObj(body);

    if (result.getInt("errcode") != 0) {
        throw new RuntimeException("企业微信API调用失败: " + result.getStr("errmsg"));
    }


return result.getJSONArray(“userlist”);
}

public static JSONObject convertToTargetFormat(JSONObject wecomUser) {

    Map<String, Object> map = new HashMap<>();
    map.put("group_id", 2);                             
    map.put("is_admin", false);             
    map.put("nickname", wecomUser.getStr("name"));       
    map.put("status", 1); 
    map.put("username", wecomUser.getStr("userid"));     


return JSONUtil.parseObj(map);
}


public static void createUser(JSONObject userData) {


HttpResponse response = HttpRequest.post(RUST_DESK_HOST +”/admin/user/create”)
.body(userData.toString())
.header(“api-token”, RUST_DESK_TOKEN)
.contentType(“application/json”)
.execute();

    if (response.getStatus() != 200) {
        System.out.println("用户创建失败: HTTP " + response.getStatus());
    }


JSONObject result = JSONUtil.parseObj(response.body());
System.out.println(“添加响应结果:”+result);
}


public static void updateAllUsersPassword() {
int page = 1;
int pageSize = 100;
int totalPages = 1;

while (page <= totalPages) {

        JSONObject userListResponse = getUserList(page, pageSize);

        if (userListResponse == null || userListResponse.getInt("code") != 0) {
            System.err.println("获取用户列表失败,页码: " + page);
            page++;
            continue;
        }


JSONObject data = userListResponse.getJSONObject(“data”);
JSONArray users = data.getJSONArray(“list”);

        totalPages = (int) Math.ceil((double) data.getInt("total") / pageSize);

        for (Object userObj : users) {
            JSONObject user = (JSONObject) userObj;
            updateUserPassword(user);
        }


page++;
}
}

public static JSONObject getUserList(int page, int pageSize) {
String url = RUST_DESK_HOST + “/admin/user/list”;

try {
HttpResponse response = HttpRequest.get(url)
.header(“api-token”, RUST_DESK_TOKEN)
.form(“page”, page)
.form(“page_size”, pageSize)
.execute();

String body = response.body();

return JSONUtil.parseObj(body);
} catch (Exception e) {
System.err.println(“获取用户列表异常: “ + e.getMessage());
return null;
}
}

public static void updateUserPassword(JSONObject user) {
int userId = user.getInt(“id”);
String username = user.getStr(“username”);
String newPassword = username + “!@#123”;

String url = RUST_DESK_HOST + “/admin/user/changePwd”;

try {
if (userId >1) {
JSONObject requestBody = new JSONObject();
requestBody.set(“id”, userId);
requestBody.set(“password”, newPassword);

HttpResponse response = HttpRequest.post(url)
.body(requestBody.toString())
.header(“api-token”, RUST_DESK_TOKEN)
.contentType(“application/json”)
.execute();

JSONObject result = JSONUtil.parseObj(response.body());

if (result.getInt(“code”) == 0) {
System.out.println(“用户密码更新成功: “ + username);
} else {
System.err.println(“用户密码更新失败: “ + username +
“ | 错误信息: “ + result.getStr(“message”));
}
}
} catch (Exception e) {
System.err.println(“更新密码异常: “ + username + “ | “ + e.getMessage());
}
}

public static void main(String[] args) {

    updateAllUsersPassword(); 
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#### **Oauth2 接入(GitHub)演示**

添加对应 Oauth2 配置

![](https://qt.qiongzhou.eu.org/webp/image-20250711221332982.png)

* 对于`Google``Github`, `Issuer``Scopes`不需要填写.

* 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email``preferred_username`

* `github oauth app``Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App` 中创建, 地址 [https://github.com/settings/developers](https://github.com/settings/developers) `callback URL 填写`{uri}/api/oauth/callback

* `Authorization callback URL`填写`http:///api/oidc/callback` ,比如`http://127.0.0.1:21114/api/oidc/callback`

前往 GitHub oauth app 配置 [https://github.com/settings/developers](https://github.com/settings/developers)

![](https://qt.qiongzhou.eu.org/webp/image-20250711221939594.png)

**rustdesk 页面配置**

**![](https://qt.qiongzhou.eu.org/webp/image-Oxeb.png)**

这样是存在 bug

![](https://qt.qiongzhou.eu.org/webp/image-20250711222302517.png) 我们直接调用 api 添加该字段也不行,这个 bug 应该是由于使用 sqlite 会出现,mysql 正常

curl —location —request POST ‘http://192.168.73.129:21114/api/admin/oauth/create‘ \
—header ‘api-token: 60aca81100daccf883c66f32b45d7b72’ \
—header ‘Content-Type: application/json’ \
—data ‘{
“id”: 0,
“op”: “”,
“oauth_type”: “github”,
“issuer”: “”,
“client_id”: “2221”,
“client_secret”: “1123”,
“redirect_url”: “”,
“scopes”: “”,
“auto_register”: true,
“pkce_enable”: false,
“pkce_method”: “S256”
}’

```

完成后页面展示

第三方接入与 OIDC 接入

根据 up 主的查阅 OIDC 算比较前沿的,国内支持厂商并不多,好像企业微信在 23 年已经内测了,如果内部业务系统支持可以对接,或者查询所使用的系统看有没有对接的可能,或者直接简单开发对接 api 实现自定义 Oauth2 登录

其他权限管理

这里的话各位小伙伴可以自行探索,根据自己的需求来使用地址簿、标签、分组等等