跳转至

登录(LoginController)

提供平台登录、注销、用户注册、找回密码、第三方免登(飞书/钉钉)、代理登录、调试登录、验证码与短信验证码、登录页多语言字段与企业域列表等能力。是 runtime 模块登录/认证域的核心控制器。

  • 接口类型:REST 资源(@RestController
  • 基址${myapps.context-path.runtime:}(即 runtime context 根,端点路径各自独立,未统一加前缀)
  • Tag:登录模块

公共说明

  • 响应结构(非统一 Resource):除 GET /GET /api/login(HTTP 302 重定向)和 POST /api/runtime/login/registerUser(返回裸字符串 token / "error")外,其余端点返回控制器私有的 result(...) JSON 结构,字段名为 resultCode/msg,而非统一 Resource 的 errcode/errmsg
    {
      "resultCode": "1",      // "1"=成功,"0"=失败,个别端点用 "ok"
      "msg": "登陆成功",
      "<dataName1>": <任意>,   // 动态业务字段(如 returnUrl、accessToken、checkcodeImg、multiLangWordList、result、domainList、userList、proxyUsers、status、data 等)
      "<dataName2>": <任意>
    }
    
    失败时 resultCode 多为 "0"msg 为失败原因(可能含多语言占位符如 {*[core.user.notexist]*})。
  • 鉴权(据源码 RestSecurityHandlerInterceptor:拦截器仅注册到 /api/runtime/**/api/rest/bpm/**,并在内部按正则豁免以下路径——
  • /api/runtime/login.*(覆盖本控制器下 /api/runtime/login/ 开头的全部端点,包括登录、注册、找回密码、验证码、多语言、企业域列表、代理登录、短信发送等)→ 豁免,无需 accessToken。
  • /api/runtime/dingding/authlogin(钉钉免登)→ 豁免
  • /api/runtime/logout(退出登录)→ 不豁免,需通过 accessToken(query / header / Cookie 中任一)或 debugToken 标识用户。
  • /api/debuglogin/**(4 个调试登录端点)与 GET /GET /api/login → 不在拦截器覆盖范围,拦截器本身不校验;走通用 Servlet 过滤器链(RuntimeSecurityFilter 等)。
  • 登录态令牌:登录成功后服务端通过 Security.generateToken(userId) 生成 JWT,写入名为 accessToken 的 Cookie(调试登录写入 debugToken Cookie);该 Cookie 也是后续受保护接口的凭证。
  • 状态码:所有端点成功返回 HTTP 200;业务结果由响应体 resultCode 体现,未与 HTTP 状态码绑定。

1. 访问主页面

访问 runtime 根路径时,将请求重定向到门户首页。

  • 接口类型:REST 资源(HTTP 302 重定向)
  • 请求方式GET
  • 请求路径/(完整:{runtime-context}/
  • 鉴权:否(据源码:不在 RestSecurityHandlerInterceptor 覆盖范围)
  • Tag:登录模块

请求参数

无。

请求示例

GET / HTTP/1.1

响应

结构:HTTP 302 重定向,Location: /static/portal/vue/index.html。无响应体。


2. 访问登录页面

重定向到前台登录页面。

  • 接口类型:REST 资源(HTTP 302 重定向)
  • 请求方式GET
  • 请求路径/api/login(完整:{runtime-context}/api/login
  • 鉴权:否(据源码:不在 RestSecurityHandlerInterceptor 覆盖范围)
  • Tag:登录模块

请求参数

无。

请求示例

GET /api/login HTTP/1.1

响应

结构:HTTP 302 重定向,Location: signon/login.html。无响应体。


3. 飞书免登录

通过飞书免登授权码换取平台用户并完成登录,登录成功后返回前端跳转地址并写入 accessToken Cookie。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/feisuhAuthLogin/domain/{domainId}/code/{code}(完整:{runtime-context}/api/runtime/login/feisuhAuthLogin/domain/{domainId}/code/{code}
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
domainId path string 企业域Id
code path string 飞书免登授权码
loginway query string 登录端标识;非空时跳转移动端首页(如 mobile

请求示例

POST /api/runtime/login/feisuhAuthLogin/domain/__DmAINID__/code/__CODE__?loginway=mobile HTTP/1.1

响应

结构:私有 result JSON(见本页「公共说明 · 响应结构」)。 data 字段url(前端跳转地址,PC 端默认 /static/portal/vue/index.html#/,移动端 /static/mobile/index.html#/)。用户不存在时返回 msg 提示并指向 url: /static/signon

成功示例

{
  "resultCode": "1",
  "msg": "登陆成功",
  "url": "/static/portal/vue/index.html#/"
}

失败示例(用户不存在)

{
  "resultCode": "0",
  "msg": "该应用无该用户,请先前往企业域同步用户",
  "url": "/static/signon"
}


4. 获取登录页多语言字段

按语言获取登录页面所需的多语言文案集合,并把语言写入 userLanguage Cookie。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/getMultiLangWordList(完整:{runtime-context}/api/runtime/login/getMultiLangWordList
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
jsonObj body object 请求包体,须含 language 字段

请求体

{
  "language": "CN"
}

请求示例

POST /api/runtime/login/getMultiLangWordList HTTP/1.1
Content-Type: application/json

{
  "language": "CN"
}

响应

结构:私有 result JSON。 data 字段multiLangWordList(Map),登录页各文案键值对(如 pageLoginAccountpageLoginPasswordlogindingdingLoginwechatLoginscanCode 等)。

成功示例

{
  "resultCode": "1",
  "msg": "成功",
  "multiLangWordList": {
    "pageLoginAccount": "账号",
    "pageLoginPassword": "密码",
    "login": "登录",
    "dingdingLogin": "钉钉登录",
    "wechatLogin": "微信登录"
  }
}

失败示例

{
  "resultCode": "0",
  "msg": "失败",
  "multiLangWordList": null
}


5. 改变验证码

生成新的登录验证码图片,返回 Base64 编码的 JPG 图片字符串。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/changeCheckcodeImg(完整:{runtime-context}/api/runtime/login/changeCheckcodeImg
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

无。

请求示例

POST /api/runtime/login/changeCheckcodeImg HTTP/1.1

响应

结构:私有 result JSON。 data 字段checkcode(string),格式为 data:image/jpg;base64,<Base64 字符串>,可直接作为 <img src> 使用。

成功示例

{
  "resultCode": "1",
  "msg": "改变成功",
  "checkcode": "data:image/jpg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof..."
}


6. 获取企业域列表

返回所有启用状态的企业域名称列表、登录背景与密码加密方式,供登录页渲染。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/getDomainList(完整:{runtime-context}/api/runtime/login/getDomainList
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

无。

请求示例

POST /api/runtime/login/getDomainList HTTP/1.1

响应

结构:私有 result JSON。 data 字段result(object),含 domainList(企业域名称数组)、loginBackground(登录页背景资源路径)、encryptionMode(密码加密模式,默认 "0")。

成功示例

{
  "resultCode": "1",
  "msg": "成功",
  "result": {
    "domainList": ["我的公司", "demo"],
    "loginBackground": "/static/portal/images/login_bg.png",
    "encryptionMode": "0"
  }
}

失败示例

{
  "resultCode": "0",
  "msg": "失败",
  "result": null
}


7. 登录

使用企业域、账号、密码(密文)进行登录认证;成功后生成 accessToken 写入 Cookie 并返回跳转地址。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/loginWithCiphertext2(完整:{runtime-context}/api/runtime/login/loginWithCiphertext2
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
jsonObj body object 登录请求包体(字段见下)

请求体

字段 类型 必填 说明
domainName string 企业域名称
username string 登录账号
password string 登录密码(密文)。客户端加密规则:将 BASE64(rp+lp) 中的后两位 rp 与前面 lp 互换位置后传输;服务端解码后再做比对
remember string 是否记住登录(保留字段)
checkcode string 验证码(错误次数超阈值时必填)
language string 语言,默认 CN
debug string 调试标记(保留字段)
{
  "domainName": "我的公司",
  "username": "admin",
  "password": "00YWRtaW4=",
  "remember": "0",
  "language": "CN"
}

请求示例

POST /api/runtime/login/loginWithCiphertext2 HTTP/1.1
Content-Type: application/json

{
  "domainName": "我的公司",
  "username": "admin",
  "password": "00YWRtaW4="
}

响应

结构:私有 result JSON。 data 字段returnUrl(登录成功后的跳转地址,默认 ../signon/dispatcher.html;代理场景为 ../login/agent.html?id=<userId>)、checkcodeImg(验证码图片 Base64,需要时返回)、accessToken(登录成功后的访问令牌,同时写入 Cookie)。

业务校验: - 企业域为空 → {*[cn.myapps.core.domain.label.name.illegal]*} - 企业域不存在或禁用 → {*[core.domain.notexist]*} - 用户不存在 → {*[core.user.notexist]*} - 账号已锁定 → 该账号已锁定 - 密码已过期 → 密码已过期 - 密码错误累计计数(写入 SIGNON_LOGIN_CACHE_KEY 缓存)

成功示例

{
  "resultCode": "1",
  "msg": "登陆成功",
  "returnUrl": "../signon/dispatcher.html",
  "checkcodeImg": "",
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Il9fWFhYWFhYIn0.xxxxxxxx"
}

失败示例

{
  "resultCode": "0",
  "msg": "{*[core.user.notexist]*}",
  "returnUrl": "",
  "checkcodeImg": ""
}


8. 用户注册

通过手机号在企业域内注册新用户,注册成功后返回登录 token(裸字符串)。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/registerUser(完整:{runtime-context}/api/runtime/login/registerUser
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
telephone query string 手机号
username query string 登录账号
password query string 登录密码(明文)
domainName query string 企业域名称

请求示例

POST /api/runtime/login/registerUser?telephone=13800000000&username=newuser&password=plain&domainName=%E6%88%91%E7%9A%84%E5%85%AC%E5%8F%B8 HTTP/1.1

响应

结构:裸字符串(非 JSON)。成功返回 token 字符串;失败返回字符串 "error"

成功示例

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Il9fWFhYWFhYIn0.xxxxxxxx

失败示例

error


9. 找回密码

通过手机号(账号)重置登录密码。仅适用于账号为手机号的场景。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/retrievePassword(完整:{runtime-context}/api/runtime/login/retrievePassword
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
telephone query string 手机号(即登录账号)
password query string 新密码(明文,服务端会加密入库)

请求示例

POST /api/runtime/login/retrievePassword?telephone=13800000000&password=newplain HTTP/1.1

响应

结构:私有 result JSON(resultCode 此处用 "ok")。 data 字段status(始终为 null,结果看 msg)。

成功示例(重置成功)

{
  "resultCode": "ok",
  "msg": " 密码重置成功",
  "status": null
}

失败示例(用户不存在)

{
  "resultCode": "ok",
  "msg": " 用户不存在,请注册",
  "status": null
}


10. 钉钉免登

通过钉钉免登授权码换取平台用户并完成登录,登录成功后返回带 accessToken 的前端跳转地址。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/runtime/dingding/authlogin(完整:{runtime-context}/api/runtime/dingding/authlogin
  • 鉴权:否(据源码:拦截器精确豁免 /api/runtime/dingding/authlogin
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
code query string 钉钉免登授权码
domainId query string 企业域Id
appId query string 软件(应用)Id;为 km 时跳转 KMS
formId query string 表单Id;非空时跳转到对应待办详情
docId query string 文档Id;与 formId 配合使用
isPc query boolean 是否来自 PC 端,默认 false;决定跳转 PC 或移动门户

请求示例

GET /api/runtime/dingding/authlogin?code=__CODE__&domainId=__DOMAINID__&appId=__APPID__&isPc=true HTTP/1.1

响应

结构:私有 result JSON。 data 字段returnUrl(前端跳转地址,URL 中已附带 accessToken 与其它上下文参数)。用户不存在时 resultCode=0,无 returnUrl

成功示例

{
  "resultCode": "1",
  "msg": "登陆成功",
  "returnUrl": "/static/portal/vue/index.html?accessToken=eyJhbGciOiJIUzI1NiJ9..."
}

失败示例(用户不存在)

{
  "resultCode": "0",
  "msg": "用户不存在,请联系管理员同步"
}


11. 获取可代理登录用户

根据当前用户Id,返回其可作为代理人登录的目标用户列表。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/runtime/login/getProxyUsers/{userid}(完整:{runtime-context}/api/runtime/login/getProxyUsers/{userid}
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
userid path string 代理人用户Id

请求示例

GET /api/runtime/login/getProxyUsers/__USERID__ HTTP/1.1

响应

结构:私有 result JSON。 data 字段proxyUsers(数组),元素为 { id, name, avatar };不在代理有效期内的用户被过滤。

成功示例

{
  "resultCode": "0",
  "msg": "",
  "returnUrl": "",
  "proxyUsers": [
    { "id": "__UID1__", "name": "lisi", "avatar": "" },
    { "id": "__UID2__", "name": "wangwu", "avatar": "" }
  ]
}

说明:本端点 resultCode 固定返回 "0",结果应通过 proxyUsers 字段判断。


12. 代理登录

以代理身份登录到指定用户,写入新的 accessToken Cookie。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/runtime/login/loginProxy/{userid}(完整:{runtime-context}/api/runtime/login/loginProxy/{userid}
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
userid path string 被代理的目标用户Id

请求示例

GET /api/runtime/login/loginProxy/__USERID__ HTTP/1.1

响应

结构:私有 result JSON。 data 字段returnUrl(成功时为 ../signon/dispatcher.html,失败时为空字符串)。

成功示例

{
  "resultCode": "1",
  "msg": "登陆成功",
  "returnUrl": "../signon/dispatcher.html"
}

失败示例

{
  "resultCode": "0",
  "msg": "登陆失败",
  "returnUrl": ""
}


13. 调试登录-获取企业域列表

调试登录场景下获取所有启用状态的企业域名称列表。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/debuglogin/getDomainList(完整:{runtime-context}/api/debuglogin/getDomainList
  • 鉴权:否(据源码:路径不在 RestSecurityHandlerInterceptor/api/runtime/** 覆盖范围)
  • Tag:登录模块

请求参数

无。

请求示例

GET /api/debuglogin/getDomainList HTTP/1.1

响应

结构:私有 result JSON。 data 字段domainList(企业域名称数组)。

成功示例

{
  "resultCode": "1",
  "msg": "成功",
  "domainList": ["我的公司", "demo"]
}

失败示例

{
  "resultCode": "0",
  "msg": "失败",
  "domainList": null
}


14. 调试登录-获取用户列表

按企业域名称(及可选用户名前缀)模糊查询用户登录账号列表,供调试登录页选择。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/debuglogin/getUserList(完整:{runtime-context}/api/debuglogin/getUserList
  • 鉴权:否(据源码:路径不在 RestSecurityHandlerInterceptor/api/runtime/** 覆盖范围)
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
domainName query string 企业域名称
username query string 用户名模糊关键字,可空

请求示例

GET /api/debuglogin/getUserList?domainName=%E6%88%91%E7%9A%84%E5%85%AC%E5%8F%B8&username=admin HTTP/1.1

响应

结构:私有 result JSON。 data 字段userList(用户登录账号字符串数组)。

成功示例

{
  "resultCode": "1",
  "msg": "成功",
  "userList": ["admin", "lisi", "wangwu"]
}

失败示例

{
  "resultCode": "0",
  "msg": "失败",
  "userList": null
}


15. 调试登录-获取多语言字段

调试登录场景下按语言获取登录页所需的多语言文案集合。

  • 接口类型:REST 资源
  • 请求方式GET
  • 请求路径/api/debuglogin/getMultiLangWordList(完整:{runtime-context}/api/debuglogin/getMultiLangWordList
  • 鉴权:否(据源码:路径不在 RestSecurityHandlerInterceptor/api/runtime/** 覆盖范围)
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
language query string 语言标识,如 CNENTW

请求示例

GET /api/debuglogin/getMultiLangWordList?language=CN HTTP/1.1

响应

结构:私有 result JSON。 data 字段multiLangWordList(Map),登录页各文案键值对。

成功示例

{
  "resultCode": "1",
  "msg": "成功",
  "multiLangWordList": {
    "pageLoginAccount": "账号",
    "pageLoginPassword": "密码",
    "login": "登录"
  }
}

失败示例

{
  "resultCode": "0",
  "msg": "失败",
  "multiLangWordList": null
}


16. 调试登录-登录

调试登录专用:按企业域 + 用户名直接登录(无需密码),生成的 token 写入 debugToken Cookie。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/debuglogin/loginWithCiphertext2(完整:{runtime-context}/api/debuglogin/loginWithCiphertext2
  • 鉴权:否(据源码:路径不在 RestSecurityHandlerInterceptor/api/runtime/** 覆盖范围)
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
jsonObj body object 调试登录请求包体

请求体

字段 类型 必填 说明
domainName string 企业域名称
username string 登录账号;若含括号(多账号场景)取括号前部分
{
  "domainName": "我的公司",
  "username": "admin"
}

请求示例

POST /api/debuglogin/loginWithCiphertext2 HTTP/1.1
Content-Type: application/json

{
  "domainName": "我的公司",
  "username": "admin"
}

响应

结构:私有 result JSON。 data 字段returnUrl(成功为 ../signon/dispatcher.html,代理场景为 ../login/agent.html?id=<userId>)、checkcodeImg(始终为空字符串)。

成功示例

{
  "resultCode": "1",
  "msg": "登陆成功",
  "returnUrl": "../signon/dispatcher.html",
  "checkcodeImg": ""
}

失败示例

{
  "resultCode": "0",
  "msg": "登陆失败",
  "returnUrl": "",
  "checkcodeImg": ""
}


17. 退出登录

注销当前用户的登录态,记录注销日志(按企业域配置),并返回登出后的跳转地址。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/logout(完整:{runtime-context}/api/runtime/logout
  • 鉴权:是(据源码:拦截器覆盖 /api/runtime/**,且 /api/runtime/logout 不在豁免名单,需 accessToken 或 debugToken)
  • Tag:登录模块

请求参数

无(用户身份从请求中的 accessToken / debugToken 解析)。

请求示例

POST /api/runtime/logout HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...

响应

结构:私有 result JSON(resultCode 此处用 "ok")。 data 字段data(string),登出后的重定向地址;若认证类型为 SSO,返回配置的 SSO 登出地址,否则为空字符串。

成功示例

{
  "resultCode": "ok",
  "msg": "ok",
  "data": ""
}


18. 发送短信验证码

向指定用户的手机号发送短信验证码内容。

  • 接口类型:REST 资源
  • 请求方式POST
  • 请求路径/api/runtime/login/smsSend(完整:{runtime-context}/api/runtime/login/smsSend
  • 鉴权:否(据源码:拦截器正则豁免 /api/runtime/login.*
  • Tag:登录模块

请求参数

参数名 位置 类型 必填 说明
userId query/form string 接收短信的用户Id
content query/form string 短信内容

说明:源码方法签名为 doSmsSend(String userId, String content),未显式标注 @RequestParam,Spring 默认按名称绑定 query 与 form 参数均可。

请求示例

POST /api/runtime/login/smsSend?userId=__USERID__&content=您的验证码为123456 HTTP/1.1

响应

结构:私有 result JSON(resultCode 此处用 "ok")。 data 字段status(boolean),短信是否发送成功。

成功示例

{
  "resultCode": "ok",
  "msg": "发送成功",
  "status": true
}

失败示例(内部异常被吞,仍返回 ok)

{
  "resultCode": "ok",
  "msg": "发送成功",
  "status": false
}