单终端登录系统
A Project Of How To Use gRPC/Bazel/Djinni/Docker/Sqlite.
目录
项目介绍
功能简介
- 具备注册登录功能
- 一个⽤户只能在一个设备上登录,切换终端登录时,其他已登录的终端会被踢出
客户端下载链接:MyLogin
技术简介
- 客户端用Android实现,采用Djinni实现跨平台开发,业务逻辑在C层实现
- 服务端用C++实现,数据库使用SQLite3
- 使用GPRC进行远程通信,生成非对称密钥,使用SSL进行数据传输加密
- 使用Bazel构建后台项目,以及依赖管理
- 使用Docker部署项目,并使用Docker Compose编排容器
架构图
客户端
服务端
流程图
image
项目实现
接口说明
| 接口名 | 接口方法 |
|---|---|
| 用户登录 | requestUserLogin |
| 用户注册 | requestUserSign |
| 退出登录 | requestLogout |
| 检查用户在线状态 | checkConnect |
用户登录
请求方法
requestUserLogin
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| account | true | string | 用户账号 |
| password | true | string | 用户密码 |
返回参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| token | string | 用户Token |
返回结果
{
"code": 0,
"msg": "",
"data": "[token]"
}
用户注册
请求方法
requestUserSign
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| account | true | string | 用户账号 |
| password | true | string | 用户密码 |
返回参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| token | string | 用户Token |
返回结果
{
"code": 0,
"msg": "",
"data": "[token]"
}
退出登录
请求方法
requestLogout
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| token | true | string | 用户Token |
返回参数
无
返回结果
{
"code": 0,
"msg": "",
"data": ""
}
检查用户在线状态
请求方法
checkConnect
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| token | true | string | 用户Token |
返回参数
无
返回结果
{
"code": 0,
"msg": "",
"data": ""
}
错误码
公共错误码
公共错误码范围 0 ~ 99
| 错误代码 | 错误类型 | 描述 |
|---|---|---|
| 0 | 请求成功 | |
| 1 | 请求参数非法 | 后台接口接收到的参数不合法,如账号里包含字符,密码不够位数 |
模块错误码
业务逻辑错误,7位数字
组成规则:[模块][接口][具体错误]
如:1xxxzzz 账号模块,2xxxzzz 卡包模块, ......
| 错误代码 | 错误类型 | 描述 | 备注 |
|---|---|---|---|
| 1001xxx | 用户登录接口相关 | ||
| 1001001 | 账号不存在 | 根据接口传来的账号,查询数据库没有找到对应的账号信息 | |
| 1001002 | 密码初始化失败 | 对接口传来的密码,进行加密过程失败 | |
| 1001003 | 用户密码错误 | 对接口传来的密码,与数据库中该用户的密码匹对失败 | |
| 1001004 | 用户Token更新失败 | 通过账号与UID生成的Token,更新到数据库失败 | |
| 1002xxx | 用户注册接口相关 | ||
| 1002001 | 账号已经存在 | 根据接口传来的账号,查询数据库发现该账号已经存在 | |
| 1002002 | 密码初始化失败 | 对接口传来的密码,进行加密过程失败 | |
| 1002003 | 账号创建失败 | 根据账号信息新增账号到数据库失败 | |
| 1002004 | 账号信息获取失败 | 根据账号查询数据库对应账号信息失败 | |
| 1002005 | 账号会话信息创建失败 | 根据账号信息新增账号会话(Token)到数据库失败 | |
| 1003xxx | 用户退出登录接口相关 | ||
| 1003001 | Token格式错误 | 接口传来的Token格式不正确,属于非法Token | |
| 1003002 | 账号会话信息更新失败 | 更新Token信息到会话表失败 | |
| 1004xxx | 检查在线状态接口 | ||
| 1004001 | Token格式错误 | 接口传来的Token格式不正确,属于非法Token | |
| 1004002 | Token已经失效 | 根据Token中附带的过期时间,判断该Token已经失效 | |
| 1004003 | 账号已离线 | 根据Token查询会话信息,判断该账号是离线状态 | |
| 1004004 | Token校验失败 | 根据Token与数据库中Token进行比对,判断该设备不在线 |
加密说明
接口请求SSL
接口使用SSL加密认证,通过OpenSSL生成对应的密钥文件,客户端保存公钥,在Channel中加上公钥信息,服务器端通过私钥认证接口合法性,保证传输安全
密码初始化
用户注册流程,后台接收到用户的账号和密码
- 通过SHA256消息摘要算法对账号进行计算,获得摘要信息
- 将1中获得的摘要信息作为盐,与密码拼接,获得加密前信息
- 将2中获得的信息,进行MD5消息摘要计算,获得加密后的128位,用16进制表示的密码字符串
用户登录流程,后台接收到用户的账号和密码
- 通过用户传来的账号和密码,用“注册流程”加密规则获得加密后密码字符串
- 与数据库中用户的密码字符串比对,一致则登录成功,反之则登录失败。
Token生成规则
image
用户登录/注册流程,生成用户Token并返回
-
加密前Token由用户信息和当前登录信息组成
加密前Token = [用户账号]:[用户UID]:[随机6位字符串]:[登录时间戳(秒)]:[过期时间戳(秒)]
例如:"13533192331:2:172649:1552031125:1557301525"
-
将加密前Token进行对称密钥算法AES计算,获得加密后Token
Token = AES(加密前Token)
日志说明
日志规则
日志文件按日期分割,例如 2019-3-5.log
| 消息类型 | 含义 |
|---|---|
| INFO | 相关INFO信息可以让运维保留下来,可用来分析,比如接口访问信息 |
| DEBUG | 相关DEBUG信息提供给开发来用调试程序 |
| WARN | 相关WARN信息提示程序没有按照预期的运行,但不会影响到整体正常运行,需要被FIX |
| ERROR | 相关ERROR信息提示程序出现了严重错误,影响到系统的正常运行,必须被FIX |
日志样例
image
数据库说明
使用SQLite3作为数据库
| 表名 | 字段 | 类型 | 备注 |
|---|---|---|---|
| user_account | |||
| ID | INTEGER PRIMARY KEY | 用户UID | |
| ACCOUNT | CHAR | 用户账号 | |
| PASSWORD | CHAR | 用户密码 | |
| user_session | |||
| ID | INTEGER PRIMARY KEY | ||
| UID | INTEGER | 用户UID,外键关联 user_account(ID) | |
| TOKEN | CHAR | 用户Token | |
| IS_ONLINE | INTEGER | 是否在线(1.在线 0.离线) |
版本说明
| 模块 | 版本号 | 备注 | |
|---|---|---|---|
| Android端 | |||
| Android Studio | 3.2.1 | Android IDE | |
| Gradle | 4.6 | ||
| Android Plugin Version | 3.2.1 | ||
| GRPC-C++ | 1.18.0 | ||
| Protobuffer | 3.6.1 | ||
| 后端 | |||
| Ubuntu | 18.04-x86_64 | ||
| Bazel | 0.20.0 | ||
| GRPC-C++ | 1.18.0 | ||
| Docker | 18.09.1 | Community | |
| Docker Compose | 1.23.2 | ||
| 系统 | |||
| ufw | 0.35 | Ubuntu 防火墙 |
常用后端命令
| 命令 | 备注 |
|---|---|
| bazel build //source:account_server | 构建目标文件 |
| cp ./bazel-bin/source/account_server docker-src/ | 将构建成功的执行文件复制到本地docker目录 |
| docker build -t grpcserver:1.0 . | 在根目录,根据Dockerfile编写的规则,生成服务镜像 |
| docker-compose up grpcserver | 在根目录,根据docker-compose.yml编写的规则,启动并管理容器 |










网友评论