基于spring生态的基础后端开发及渗透测试流程
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
这是一篇记录如何从建仓开始到最后安全测试完整流程的笔记使用的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层 |
BOBusiness 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 |
4xxclient:
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 |
5xxserver:
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 |