---
title: 登录与鉴权
description: 登录、凭证携带、会话顶替与登录日志
pageClass: g3-api
---
# 登录与鉴权
除 `/auth/login` 外,**所有接口都需要携带凭证**。
## `POST` `/auth/login`
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `orgid` | string | 是 | 机构码,决定登录到**哪个机构的库** |
| `userid` | string | 是 | 用户账号(`b_user.b_id`) |
| `password` | string | 是 | 密码 |
```bash
curl -X POST http://localhost:8088/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"orgid":"G3HD","userid":"g3soft","password":"******"}'
```
```json
{
"code": 0,
"message": "操作成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9...",
"orgid": "G3HD",
"user": {
"id": "g3soft",
"account": "g3soft",
"name": "G3Soft"
}
}
}
```
```json
{
"code": 401,
"message": "机构码、账号或密码错误",
"data": null
}
```
**几点要注意**:
- **机构码会归一化**:去掉首尾空白并转大写,所以传 `g3hd` 与 `G3HD` 等价。
- **机构码决定数据源**:登录时按机构码加载该机构的数据库配置;机构码不存在或配置缺失会失败。
- **「账号不存在」与「密码错误」对外是同一个提示**(`机构码、账号或密码错误`),不区分——避免被用来探测账号是否存在。但**登录日志里会分别记录**真实原因,便于排查。
- **`user.id` 与 `user.account` 目前是同一个值**(字符串业务键方案:`b_user.b_id` 即账号本身)。
- 用户编码与机构码都会写进 JWT,后续请求据此路由数据源与判定权限。
## 携带凭证
所有后续请求在请求头带 Bearer token:
```bash
curl -X POST http://localhost:8088/api/data/page \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...' \
-d '{"view_name":"v_b_othercompany","order_by":"b_id ASC"}'
```
| 场景 | 结果 |
|---|---|
| 缺少或格式不对的 `Authorization` | `401` |
| token 无效 / 过期 / 签名不符 | `401` |
| token 有效但**会话已被顶替** | `40101` |
| `OPTIONS` 预检请求 | **放行**(不校验) |
| `/auth/login` | **放行**(唯一不需要凭证的业务接口) |
> **HTTP 状态码始终是 200**,鉴权失败靠响应体的 `code`(`401` / `40101`)判断。
> 不要用 HTTP 状态码或 axios 的错误拦截分支处理鉴权失败。
## 会话与顶替
服务端维护**活动会话表**,同一个「机构 + 账号」只保留一个有效会话:
```text
登录 → 生成 sessionId → 登记为活动会话
再次登录同一账号 → 旧会话被顶替
旧 token 继续用 → 返回 40101(账号已在其他设备登录)
```
**前端处理**:拿到 `401` 或 `40101` 都应**清 token、回登录页**。`40101` 建议给一句「账号已在其他设备登录」,比笼统的「登录已失效」更有助于用户理解。
> 会话是**内存态**:服务重启后全部失效,用户需重新登录。
## 登录日志
每次登录尝试都会记录,含成功与失败:
| 记录内容 | 说明 |
|---|---|
| 机构码、用户账号 | 尝试登录的身份 |
| 成功 / 失败、失败原因 | 「账号不存在」/「密码错误」 |
| 会话 ID | 登录成功时 |
| 客户端信息 | 浏览器、操作系统、设备类型 |
| IP 与归属地 | 来源地址解析 |
查询入口:`v_s_log_login` 视图(走通用查询接口)。日志表本身**不需要登录权限之外的特殊授权**,但建议只给管理员开放。
## 相关配置
| 配置项 | 说明 |
|---|---|
| `erp.auth.jwt-secret` | 签名密钥,**生产必须改**(默认值仅用于开发) |
| `erp.auth.jwt-expiration` | token 有效期,默认 `24h` |
| `erp.database.config-dir` | 机构数据库配置目录,登录时按机构码在此查找 |
## 常见错误
| 场景 | code | 说明 |
|---|---|---|
| 机构码为空 | `1000` | 「机构码不能为空」 |
| 用户 ID 为空 | `1000` | 「用户ID不能为空」 |
| 机构码、账号或密码错误 | `401` | 三者统一提示 |
| 机构码在配置目录里不存在 | `401` | 加载机构配置失败时按机构码错误处理 |
| 未带凭证访问其他接口 | `401` | —— |
| 会话被顶替 | `40101` | 需重新登录 |