Spring Boot + React 写聊天软件 Ep.1 - 后端数据库配置与用户登录注册

本系列记录了我从零开始学习 Spring + React 并完成一个小项目的经历和心得, 仅供参考, 并不是相关的教程. 项目概要见本系列 Ep.0.

首先肯定要设计一个用户注册/登录/注销/修改密码一系列用户相关的操作.

Spring 项目分层

几乎就是套路化的分层 - Controller 接受请求, Service 提供服务, DAO(Mapper) 数据持久化, Entity 表示实体.

项目下也创建了对应的 Java package 表示相关的文件.

配置数据库

起一个 MySQL + Redis 数据库, 引入 Gradle 依赖, 在配置文件中写入相关配置即可~

然后在 resources 下面创建 db/schema.sql 写入建表语句.

在 application.yaml 中添加以下代码在 MyBatis 中的映射关系自动转换驼峰和下划线命名.

开始尝试使用了 MyBatis, 觉得它还不够”自动化”, 很多地方要依靠代码生成器/手动修改, 根本原因应该是它没能做到完全的 ORM, 不能把 Entity 和数据库结构完全对应.

于是我换而转向了 JPA (Hibernate), 只需要在写好代码就能自动创表和完成相关的 CRUD, 个人感觉简洁很多.

https://www.baeldung.com/spring-boot-hibernate

API 设计

决定使用 RESTful 的 API 设计.

https://www.ruanyifeng.com/blog/2014/05/restful_api.html

马上开始选择困难症… 研究了好久该如何 restfully login.

其实 RESTful 本身应该是无状态的, 也不应该管理会话(Session), 但这里没有别的鉴权方法, 只能做出些妥协了…

参考了这个问题 https://stackoverflow.com/questions/7140074/restfully-design-login-or-register-resources

  • GET /session/new gets the webpage that has the login form
  • POST /session authenticates credentials against database
  • DELETE /session destroys session and redirect to /
  • GET /users/new gets the webpage that has the registration form
  • POST /users records the entered information into database as a new /user/xxx
  • GET /users/xxx // gets and renders current user data in a profile view
  • POST /users/xxx // updates new information about user

API 的响应 JSON 应该遵循下划线命名法, 在配置文件中添加以下内容, 同时直接排除了值为 null 的属性的返回:

1
2
3
4
5
spring:
jackson:
# snake case style for response json
property-naming-strategy: SNAKE_CASE
default-property-inclusion: non_null

Swagger

使用 Swagger 可以自动生成接口文档, Apifox 可以一键从 Swagger 导入, 节省了很多维护文档的时间.

鉴权框架选择

本来是打算直接手写一个 Interceptor 来拦截请求的, 后来上网搜索了一下发现有一些鉴权框架, 比如老牌的 Shiro 或 Spring Security.

然后就花了整整好几个小时在研读 Spring Security 和 Shiro 的文档. 真的好复杂…

后来发现新秀 Sa-Token: https://github.com/dromara/sa-token 更加适合前后端分离的项目而且简明许多, Spring Security 和 Shiro 都可能有些过于复杂且陈旧了, 需要自己修改许多东西才能适用前后端分离的场景.

1
2
3
4
5
6
7
// 简洁优雅的鉴权方式~
// 在登录时写入当前会话的账号id
StpUtil.login(10001);

// 然后在需要校验登录处调用以下方法:
// 如果当前会话未登录,这句代码会抛出 `NotLoginException` 异常
StpUtil.checkLogin();

顺便 SaToken 还提供了 BCrypt 算法, 正好可以使用它对密码进行加盐哈希.

本文采用 CC BY-NC-SA 4.0 许可协议发布.

作者: lyc8503, 文章链接: https://blog.lyc8503.net/post/my-chat-1-backend-authorization/
如果本文给你带来了帮助或让你觉得有趣, 可以考虑赞助我¬_¬