基于spring生态的基础后端开发及渗透测试流程
这是一篇记录如何从建仓开始到最后安全测试完整流程的笔记,使用的spring
生态,目的是为spring
的基础后端开发及后期渗透测试打一个模板。本篇采用springSecurity作为安全框架,搭载了redis-cache
、spring-valid
等功能,并开放了OAuth2授权登录。
本篇代码格式规范为优雅,代码大量使用java8
新特性以及apache
包下方便的工具类,能一行代码写完的就不用两行。当然本文也配备了大量注释,方便有需要的同学学习。
限于篇幅,文章内只能简短提及使用原因以及简略使用方法,具体步骤还请参考本篇附带代码或百度
代码仓库:https://github.com/23DAY01/blog_23DAY
项目初始化#
创建git仓库#
github上创建一个仓库,复制仓库地址
https://github.com/xxx/xxx.git
创建spring项目#
文件
->新建
->来自版本控制的项目
->填写仓库地址
文件初始化#
根据项目需要,更改.gitignore
并修改配置文件
测试提交#
- git命令行
git add –ignore-error **.java
git commit -m 'init'
git push --progress --porcelain origin refs/heads/master:master
- 用idea的GUI直接提交也可以
JavaBean#
设计原则#
- 设置逻辑删除字段
- 设置生成时间、更新时间字段
- 单一关联时可违反第三范式
- 不设置外键
数据表#
为不占用篇幅,数据表放在篇末
生成实体类#
诸多工具可以实现从数据库直接生成pojo实体类,本篇采用mybatis plus
Mybatis-Plus生成器生成domain、dto、vo、controller、service、serviceImpl、mapper、mapperXml
生成器模板具体见mybatis-plus使用手册
领域驱动#
这里简单描述一下领域驱动,他主要的目的是为了降低各层之间的耦合,业务层只做业务逻辑
对象 | 含义 | 作用 | 作用范围 |
---|---|---|---|
DO(Data Object) | 数据对象 | 与数据库表结构对应,通过DAO层向上传输数据源对象 | 数据库与Dao层,Dao层与Service层 |
DTO(Data Transfer Object) | 数据传输对象 | 主要用于远程调用等需大量传输对象的地方 | Sevice层和Web层 |
BO(Business Object) | 业务对象 | 业务对象,可以由 Service 层输出的封装业务逻辑的对象 | Sevice层和Web层 |
VO(View Object) | 视图对象 | 对应页面所显示的数据,将这些数据进行封装并返回 | Web层与页面 |
POJO(Plain Ordinary Java Object) | 普通Java对象 | - | - |
盗用别人的一张图来描述领域驱动
当业务不复杂的时候BO和DTO可以合成一个,VO可以直接使用DTO
概念是死的,人是活的,当团队协作开发时一定要保证大家理解的概念是一样的
本篇采用的是domain
、dto
、vo
三层
JavaBean转换#
对于pojo封装的实体类在各层之间的转换,可以采用工具进行转换
- mapStruct
- spring
- hutools
- EntityUtils
- BeanCopier
- ……
本篇采用的是mapStruct进行实体类转化
引入依赖,编写转换器即可使用。mapStruct在打包后会自动生成一段转换代码,并不是使用反射的方式去进行javabean的转换。在转换的过程中,字段名相同的字段会直接转换,不同的字段需要使用@Mapping
注解定义,对于嵌套的字段,mapStruct会在自身中自动寻找对应的转换方法。
@Mapper(componentModel = "spring" , injectionStrategy = InjectionStrategy.CONSTRUCTOR)
@Component
public interface MapStruct {
@Mappings({
@Mapping(target = "id",source = "studentId"),
})
Student studentConvert(StudentRequestVo studentRequestVo);
}
API文档#
业务状态码#
目前大家对于业务状态码的评论出现两极分化状态,详见https://www.v2ex.com/t/611572
本篇采用业务状态码,并参考微信小程序官方给出的状态码设计规则,自定义状态码
-
前三位遵循http状态码:200、400、500
-
中间两位表示错误范围(file、param、authentication等)
-
后两位表示细粒度错误类型
业务状态码已放在篇末
swagger/knife4j#
生成接口文档,导入包并配置文件Knife4jConfig
,使用@Api
@ApiOperation
@ApiParam
等标注方法和类,在写完业务逻辑后访问配置文件中配置的文档地址,即可查看全部标注过的接口
Knife4j是一个集Swagger2 和 OpenAPI3为一体的增强解决方案
接口设计#
RESTful 的核心思想就是,客户端发出的数据操作指令都是"动词 + 宾语"的结构。比如,GET /articles这个命令,GET是动词,/articles是宾语。
- GET:读取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- PATCH:更新(Update),通常是部分更新
- DELETE:删除(Delete)
宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。比如,/articles这个 URL 就是正确的
耦合处理#
通过构建常量、枚举、工具等类降低项目耦合性,减小后期维护难度
枚举常量#
constant
常量类 | 描述 |
---|---|
AuthConst | 认证常量,token过期时间、随机数种子等 |
CommonConst | 公共常量 |
DateConst | 日期常量,借鉴hutool封装的日期常量 |
OptTypeConst | 操作日志常量,操作类型等 |
RedisPrefixConst | redis常量,用于生成redis的key |
SocialLoginConst | 登录常量,oauth2相关常量 |
StatusMsgConst | 业务状态码常量 |
WebConst | 数据包常量 |
enums
- FileExtEnum
- FilePathEnum
- LoginTypeEnum
- StatusCodeEnum
- UploadModeEnum
工具类#
如果想自己造轮子可以仿照诸多工具去自己造,不想造的话直接调用即可
工具类 | 描述 |
---|---|
ArithmeticUtil.java | 浮点数算数工具,用于提供server性能计算 |
AuthUtil.java | 认证工具,用于支持SpringSecurity |
BeanCopyUtil.java | 实体类转换工具,spring自带工具 |
ConvertUtil.java | 类型转换工具 |
DateUtil.java | 日期工具 |
FileUtil.java | 文件工具 |
JsonUtil.java | Json处理工具 |
JwtUtil.java | JWT工具,用于支持SpringSecurity |
MapStruct.java | 实体类转换工具,mapStruct |
OssUtil.java | OSS工具 |
RedisUtil.java | redis工具 |
ResponseAPI.java | 封装响应体 |
EncryptUtil.java | 加解密工具 |
StringUtil.java | 字符串工具 |
WebUtil.java | 网络工具,处理数据包 |
异常处理#
GlobalExceptionHandler
利用@RestControllerAdvice
和@ExceptionHandler
注解实现异常统一处理
目前对于异常自定义的写法有很多,本篇采用的是根据多篇文章和Java特性自己总结出来的一种写法,主旨依旧是降低耦合、提高复用性
自定义异常,并继承BaseException,复写withErrorMessage
和withErrorCodeEnum
即可
对于异常处理的流程:
-
DAO
- 尽量不 catch 任何异常, 该向上抛就抛
- 不用记录 log 日志, 或者仅使用 logger.debug() 记录
-
Service
- 对于一些关键问题,应该及时
throw
异常, 以确保事务完整 - Service 层一般的日志级别, 应该用 logger.debug() 记日志
- 对于一些关键问题,应该及时
-
Controller 层:
- Controller 层负责组装 Service, 在关键步骤上应该加日志输出 (info 级别)
- Controller 层不应再主动 throw 异常
-
统一异常处理层:
通过 json 或 UI 返回详细的报错信息, 包括 HttpStatus 和详尽的 ErrorCode/ErrorMessage
日志框架#
本篇采用slf4j+logback记录日志
导入包并进行文件配置logback-spring.xml`
可以通过@Log4j2
注解,在方法内部直接使用log即可
缓存技术#
为了提高性能,引入缓存技术,目前springCache的实现有很多种
- GENERIC
- JCACHE
- EHCACHE
- HAZELCAST
- INFINISPAN
- COUCHBASE
- REDIS
- CACHE2K
- CAFFEINE
- SIMPLE
- NONE
本篇采用redis,继承CachingConfigurerSupport
复写配置方法即可自定义key与过期时间等
首先连接redis,进行文件配置RedisConfig
,编写redisUtil
方便redis数据操作,编写配置文件CacheConfig
并选定redis作为缓存类型即可
注解:
@Cacheable
:当重复(n>1)调用该方法时,不次执行方法体,其结果直接从缓存中找到并返回@CachePut
:确保方法调用即执行,执行后更新缓存@CacheEvict
:@Cachable
注解的反向操作,它负责从给定的缓存中移除一个值@Caching
:@Caching
是一个组注解,可以为一个方法定义提供基于@Cacheable
、@CacheEvict
或者@CachePut
注解的数组@CacheConfig
:在@CacheConfig
注解中定义了类级别的缓存和自定义键生成器
切面编程#
spring里可以有三种方法实现切面编程,过滤器、拦截器、切面
三者的顺序为:过滤器->拦截器->切面
可以根据业务需要使用三者中的任意一个进行业务逻辑的编写
拦截器可以访问controller上下文、值栈里的对象,而过滤器不能访问
拦截器可以获取IOC容器中的各个bean,而过滤器就不行
操作日志#
如果有对人员的行为进行记录的需求,则可以通过自定义注解OptLog
,然后写一个切面OptLogAspect
,并配置切入点即可实现对重点资产的操作行为记录
接口限流#
实现对部分接口的接口限流操作,防止人员恶意访问接口。通过自定义注解AccessLimit
,通过实现HandlerIntercept
生成自定义拦截器ApiAccessRestrictionInterceptor
,注入到spring里面,并在WebMvcConfigurer
中添加拦截器
重复提交限制#
实现对部分接口的重复提交限制。通过自定义注解RepeatSubmit
,通过实现HandlerIntercept
生成自定义拦截器RepeatSubmitInterceptor
,注入到spring里面,并在WebMvcConfigurer
中添加拦截器
安全框架#
认证安全#
本篇实现的是1.5次开发的springSecurity,复写了一部分的springSecurity的处理器,实现了部分的定制,这一部分内容推荐大家自己debug一下源码,这样会更容易理解
采用session管理用户,session信息保存在redis里面
所有bean注入全部放入SecurityBeanCreateConfig
本篇由于重写了UsernamePasswordAuthenticationFilter
,所以对于springSecurity
的原有配置做了比较大的改动,配置起来较为麻烦
认证#
继承WebSecurityConfigurerAdapter
对configure
复写,对http
进行配置
- formLogin
- 复写
loadUserByUsername
- 认证成功处理器
authenticationSuccessHandler
- 认证失败处理器
authenticationFailHandler
- 登录url
- 复写
- logout
- 登出成功处理器
logoutSuccessHandler
- 登出url
- 登出成功处理器
- authorizeRequests
- 密码比对策略
DaoAuthenticationProviderImpl
- 自定义接口拦截规则
filterInvocationSecurityMetadataSource
- 自定义权限提取规则
accessDecisionManager
- 密码比对策略
- rememberMe
- 其他配置
- 前认证检查
preAuthenticationChecks
- 后认证检查
postAuthenticationChecks
- 前认证检查
会话管理#
利用@EnableRedisHttpSession
开启redis管理session
在WebSecurityConfig
中配置http.session
- sessionId策略
- session过期策略
- session并发策略
- session集群会话处理
- session错误策略
上述部分策略由CompositeSessionAuthenticationStrategy
集合后注入到LoginAuthenticationFilter
其余策略注入到springSecurity
配置的session管理器中
验证码#
本篇采用图形验证码,先编写配置文件CaptchaConfig
,VerificationCodeFilter
实现OncePerRequestFilter
在WebSecurityConfig
中的http.addFilterAt
将VerificationCodeFilter
添加过滤器在UsernamePasswordAuthenticationFilter
在前面即可
数据流恢复#
通过BodyReaderRequestWrapper
和RepeatableFilter
恢复数据流,通过repeatableFilterRegistration
方法注册,解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题
将取出来的字符串,再次转换成流,然后把它放入到新request 对象中,在chain.doFiler方法中 传递新的request对象
网络配置#
实现WebMvcConfigurer
,配置定义的拦截器,解决跨域问题以及资源处理器问题
数据校验#
由于对外接口全部体现为VO,我们在VO的对应字段上加入@Valid
的相关注解,并在参数位置使用@Valid
即可实现对数据的校验
- 针对 UI 输入检查, 如果 js 前端检查有困难, 可以在 Controller 层使用 Pojo validation 手段做检查, 然后前端使用 ajax 拿到校验结果. 检查过程没有触发 UI 完整渲染, 用户体验会很好
- Controller 层使用 validation 进行检查, 可以在视图函数的形参上检查, 或者在视图函数内部检查.
- Service 层, 使用 Assert 进行数据验证
- DAO 层, 不做任何数据验证
会话监听#
通过session
监听器对session
的创建、销毁等行为进行自定义,其中就包括存在于session
里面的id,即每次会话产生一次作用的javabean
RedisHttpSessionListener
通过实现HttpSessionListener
能监听session
的创建销毁,实现HttpSessionAttributeListener
能监听session
里面的键值的创建销毁,然后将RedisHttpSessionListener
作为bean注入到spring里面就可以实现监听了
注入检测#
通过加一层过滤器实现对输入的安全过滤
定义过滤器后写一个wrapper
把过滤器增强,重写里面的getParam
等方法,然后将过滤器加入过滤器链中,从而实现过滤
策略#
文件上传策略#
通过构建文件上传上下文UploadStrategyContext
来存储全局文件上传参数,UploadStrategy
接口和AbstractUploadStrategyImpl
抽象类,通过继承可实现本地文件上传LocalUploadStrategyImpl
,oss文件上传OssUploadStrategyImpl
等上传策略
登录策略#
策略构建方法同上,可以构建qq登录、微博登录、邮箱登录方法
业务逻辑#
介绍本篇重要利用的某些语法,主要为java8
新特性、自定义分页、自定义响应包等
Optional#
主要用于对null的判断,利用ofNullable
、isPresent
等
Stream#
流的操作包含如下三个部分:创建流、中间流、关闭流。筛选、去重、映射、排序属于流的中间操作,收集属于终止操作。Stream是流操作的基础关键类
通过流操作可以更优雅快速的实现对javaBean
的处理
先通过stream生成流,再通过map
、distinct
等处理流,最后收集流
分页#
在mybatisplus
自带的page
的基础上构建PageUtil
,构建了一个仅存在于一次request
的page
通过一个过滤器实现对参数内current
、size
的获取,在控制层之前构建出page
,从而实现在参数内无需出现分页参数
通过PageUtil
可以解决返回参数时无法知道total
的问题
最后通过pageResult
封装一下分页bean
即可
注意:page使用前后是一个实体
CompletableFuture#
使用CompletableFuture
可以实现异步任务,当前后业务逻辑无关时可以将耗时较长的方法设为异步任务
ResponseAPI#
通过自定义响应包,将业务状态码与状态信息、响应体封装在一起
collections4#
对于mybatis-plus
的lambdaQuery
或contains
等需要判空的地方可以使用emptyIfNull
、isNotEmpty
等方法,方便编写业务逻辑
定时任务#
对于游客用户的地域统计可以采用定时任务的形式,统计数据存入redis即可
上线部署#
本篇用的是docker-compose去部署这个博客系统,在application.yml
中将active
字段设置为prod
,然后创建application-prod.yml
配置文件,将上线部署的环境变量配置进去即可,避免将本地配置暴露
把利用到的中间件等配置文件写好,利用docker-compose去构建这些docker容器即可,记得将容器放在一个网络内,而每个容器的ip或域名与其名字是一样的,也就是我们在application-prod.yml
中可以直接使用容器名作为ip
另外,本篇用另一个域名处理管理员对应操作,nginx和vue打包时需要对应两个文件
安全测试#
容灾备份#
The end#
数据表#
day_article
文章表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_id | int | not null | 作者id |
category_id | int | null;default null | 分类id |
article_cover | varchar | null;default null | 文章封面 |
article_content | longtext | not null | 文章内容 |
article_title | varchar | not null | 文章标题 |
type | int | not null;default 0(1原创 2转载 3翻译) | 文章类型 |
original_url | varchar | null;default null | 原文链接 |
is_top | tinyint | not null;default 0(0否 1是) | 是否置顶 |
status | int | not null;default 1(1公开 2私密 3草稿) | 文章状态 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_article_tag
文章标签关系表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
article_id | int | not null | 文章id |
tag_id | int | not null | 标签id |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_category
分类表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
category_name | varchar | not null | 分类名称 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_chat_record
聊天记录表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_id | int | null;default null | 用户id |
nickname | varchar | not null | 用户昵称 |
avatar | varchar | not null | 用户头像 |
content | varchar | not null | 聊天内容 |
ip_address | varchar | not null | ip地址 |
ip_source | varchar | not null | ip来源 |
type | int | not null | 记录类型 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_comment
评论表
除一级评论(顶级评论)外,其他嵌套评论均归为二级评论
parent_id是父评论id
top_id是顶级评论
reply_user_id是当前comment作为回复时,被回复的评论的用户id,属于冗余设计
user_id是当前comment的用户id
affiliation_id是属主的id
type是属主的类型
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_id | int | not null | 用户id |
affiliation_id | int | null;default null | 所属主体id |
type | int | not null;default 0(1文章 2友链 3说说) | 评论类型 |
comment_content | text | not null | 评论内容 |
reply_user_id | int | null;default null | 回复用户id |
parent_id | int | null;default null | 父评论id |
top_id | int | null;default null | 顶级评论id |
is_review | tinyint | not null;default 0(0否 1是) | 是否审核 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_friend_link
友链表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
link_name | varchar | not null | 链接名称 |
link_avatar | varchar | not null | 链接头像 |
link_address | varchar | not null | 链接地址 |
link_info | varchar | not null | 链接简介 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_menu
菜单表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
menu_name | varchar | not null | 菜单名称 |
menu_path | varchar | not null | 菜单路径 |
compoent | varchar | not null | 组件 |
icon | varchar | not null | 菜单图标 |
order_num | int | not null | 排序级别 |
parent_id | int | not null | 父菜单id |
is_hidden | tinyint | not null;default 0(0否 1是) | 是否隐藏 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_message
留言表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
nickname | varchar | not null | 用户昵称 |
avatar | varchar | not null | 用户头像 |
message_content | varchar | not null | 留言内容 |
ip_address | varchar | not null | ip地址 |
ip_source | varchar | not null | ip来源 |
speed | int | null;default null | 弹幕速度 |
is_review | tinyint | not null;default 0(0否 1是) | 是否审核 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_operation_log
操作日志表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
opt_module | varchar | not null | 操作模块 |
opt_type | varchar | not null | 操作类型 |
opt_url | varchar | not null | 操作url |
opt_method | varchar | not null | 操作方法 |
opt_desc | varchar | not null | 操作描述 |
request_param | longtext | not null | 请求参数 |
request_method | varchar | not null | 请求方式 |
response_data | longtext | not null | 响应数据 |
user_id | int | not null | 用户id |
nickname | varchar | not null | 用户昵称 |
ip_address | varchar | not null | ip地址 |
ip_source | varchar | not null | ip来源 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_page
页面表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
page_name | varchar | not null | 页面名称 |
page_label | varchar | null;default null | 页面标签 |
page_cover | varchar | not null | 页面封面 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_resource
资源表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
resource_name | varchar | not null | 资源名称 |
url | varchar | null;default null | 权限路径 |
request_method | varchar | null;default null | 请求方式 |
parent_id | int | null;default null | 父权限id |
is_anonymous | tinyint | not null;default 0(0否 1是) | 是否可以匿名访问 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_role
角色表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
role_name | varchar | not null | 角色名称 |
role_label | varchar | not null | 角色描述 |
is_disable | tinyint | not null;default 0(0否 1是) | 是否禁用 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_role_menu
角色菜单表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
role_id | int | null;default null | 角色id |
menu_id | int | null;default null | 菜单id |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_role_resource
角色资源表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
role_id | int | null;default null | 角色id |
resource_id | int | null;default null | 资源id |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_tag
标签表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
tag_name | varchar | not null | 标签名称 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_talk
说说表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_id | int | not null | 用户id |
content | varchar | not null | 说说内容 |
image | varchar | null;default null | 图片 |
is_top | tinyint | not null;default 0(0否 1是) | 是否置顶 |
status | tinyint | not null;default 1(0公开 1私密) | 说说状态 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_view
访问量表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
view_count | int | not null | 访问量 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_user_auth
用户权限表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_info_id | int | not null | 用户信息id |
username | varchar | not null | 用户名 |
password | varchar | not null | 密码 |
login_type | int | not null | 登录类型 |
ip_address | varchar | null;default null | ip地址 |
ip_source | varchar | null;default null | ip来源 |
is_disabled | tinyint | not null;default 0(0否 1是) | 是否禁用 |
last_login_time | datetime | null;default null | 上次登录时间 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_user_info
用户信息表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键id |
varchar | null;default null | 邮箱 | |
nickname | varchar | not null | 用户昵称 |
avatar | varchar | not null;default ‘’ | 用户头像 |
intro | varchar | null;default null | 用户介绍 |
website | varchar | null;default null | 个人网站 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_user_role
用户角色表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
user_id | int | null;default null | 用户id |
role_id | int | null;default null | 角色id |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
day_website_config
网站配置表
字段名 | 字段类型 | 属性 | 备注 |
---|---|---|---|
id | int | not null | 主键 |
name | varchar | not null | 网站名称 |
intro | varchar | null;default null | 网站简介 |
author | varchar | null;default null | 网站作者 |
url | varchar | null;default null | 网站地址 |
notice | varchar | null;default null | 网站通知 |
about | varchar | null;default null | 关于我 |
github | varchar | null;default null | github |
varchar | null;default null | qq号 | |
beian_id | varchar | null;default null | 备案号 |
author_avatar | varchar | null;default ‘’ | 作者头像 |
user_avatar | varchar | null;default‘’ | 游客头像 |
deleted | tinyint | null;default 0(0否 null是) | 逻辑删除 |
create_time | datetime | not null | 创建时间 |
update_time | datetime | null;default null | 修改时间 |
业务状态码#
2xx:#
http状态码 | 错误范围 | 细粒度错误 | 业务状态码 | 错误原因 | 错误名称 |
---|---|---|---|---|---|
200 | 00 | 00 | 200000 | null | OK |
4xx(client):#
http状态码 | 错误范围 | 细粒度错误 | 业务状态码 | 错误原因 | 错误名称 |
---|---|---|---|---|---|
400 | 01 | 01 | 4000101 | 参数缺失 | ACCESS_PARAM_MISSING |
400 | 01 | 02 | 4000102 | 参数类型错误 | ACCESS_PARAM_TYPE_ERROR |
400 | 01 | 03 | 4000103 | 参数校验错误 | ACCESS_PARAM_NOT_VALID |
400 | 02 | 01 | 4000201 | 文件为空 | FILE_EMPTY |
400 | 02 | 02 | 4000202 | 文件类型错误 | FILE_TYPE_ERROR |
400 | 03 | 01 | 4000301 | 尚未登录 | AUTH_NO_LOGIN |
400 | 03 | 02 | 4000302 | 缺少权限 | AUTH_PERMISSION_DENIED |
400 | 03 | 03 | 4000303 | 认证失败 | AUTH_UorP_ERROR |
400 | 03 | 04 | 4000304 | 用户名为空 | AUTH_USERNAME_EMPTY |
400 | 03 | 05 | 4000305 | 账号不存在 | AUTH_USER_NOT_FOUND |
400 | 03 | 06 | 4000306 | 认证失败 | AUTH_FAILED |
400 | 03 | 07 | 4000307 | 校验码错误 | AUTH_CODE_ERROR |
400 | 03 | 08 | 4000308 | 校验码为空 | AUTH_CODE_MISSING |
400 | 03 | 09 | 4000309 | session过期 | AUTH_SESSION_TIMEOUT |
400 | 03 | 10 | 4000310 | 访问登录接口方法错误 | AUTH_METHOD_NOT_AVAILABLE |
400 | 03 | 11 | 4000311 | 账号已在别处登录 | AUTH_SESSION_CONCURRENCY_MAX |
400 | 03 | 12 | 4000312 | 用户账号已锁定 | AUTH_USER_ACCOUNT_LOCKED |
400 | 03 | 13 | 4000313 | 用户账号不可用 | AUTH_USER_ACCOUNT_DISABLED |
400 | 03 | 14 | 4000314 | 用户账号已过期 | AUTH_USER_ACCOUNT_EXPIRED |
400 | 03 | 15 | 4000315 | 用户账号密码过期 | AUTH_USER_CREDENTIALS_EXPIRED |
400 | 03 | 16 | 4000316 | 用户名已存在 | AUTH_USER_USERNAME_REPEAT |
400 | 03 | 17 | 4000317 | 密码错误 | AUTH_PASSWORD_ERROR |
400 | 03 | 18 | 4000318 | qq登录失败 | AUTH_QQ_ERROR |
400 | 04 | 01 | 4000401 | 接口访问频繁 | API_ACCESS_FREQUENT |
400 | 04 | 02 | 4000402 | 重复提交 | API_REPEAT_SUBMIT |
400 | 04 | 03 | 4000403 | 接口访问方法错误 | API_ACCESS_METHOD_ERROR |
400 | 05 | 01 | 4000501 | 检测到xss或sql注入 | SECURITY_CHECK_XSSorSQL |
400 | 10 | 01 | 4001001 | 文章不存在 | ARTICLE_MISSING |
400 | 11 | 01 | 4001101 | 说说不存在 | TALK_MISSING |
400 | 12 | 01 | 4001201 | 分类已存在 | CATEGORY_NAME_REPEAT |
400 | 12 | 02 | 4001202 | 分类不存在 | CATEGORY_MISSING |
400 | 12 | 03 | 4001203 | 分类下存在文章 | CATEGORY_ARTICLE_RELATION |
400 | 13 | 01 | 4001301 | 标签已存在 | TAG_NAME_REPEAT |
400 | 13 | 02 | 4001302 | 标签不存在 | TAG_MISSING |
400 | 13 | 03 | 4001303 | 标签下存在文章 | TAG_ARTICLE_RELATION |
400 | 14 | 01 | 4001401 | 菜单下存在角色 | MENU_ROLE_RELATION |
400 | 15 | 01 | 4001501 | 资源下存在角色 | RESOURCE_ROLE_RELATION |
400 | 99 | 01 | 4009901 | 未知异常 | UNKNOWN_CLIENT_ERROR |
5xx(server):#
http状态码 | 错误范围 | 细粒度错误 | 业务状态码 | 错误原因 | 错误名称 |
---|---|---|---|---|---|
500 | 01 | 01 | 5000101 | 参数封装失败 | PARAM_OPERATION_ERROR |
500 | 02 | 01 | 5000201 | 文件上传失败 | FILE_UPLOAD_ERROR |
500 | 02 | 02 | 5000202 | 文件下载失败 | FILE_DOWNLOAD_ERROR |
500 | 04 | 01 | 5000401 | 数据库异常 | SQL_ERROR |
500 | 04 | 02 | 5000402 | redis连接异常 | REDIS_CONNECTION_ERROR |
500 | 99 | 01 | 5009901 | 运行时未知异常 | UNKNOWN_RUNTIME_ERROR |
500 | 99 | 02 | 5009902 | 系统未知异常 | UNKNOWN_SYSTEM_ERROR |
作者:23DAY
出处:https://www.cnblogs.com/23DAY/p/17090383.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具