文章目录

项目业务层
在前两个博文中,已经实现了一些功能,该篇将继续处理剩下的功能。
一、实现发布博客
- 约定前后端交互接口
好的,我帮你把这个接口整理成规范的接口文档格式,包含核心的请求和响应信息:
基本信息
- 接口地址 :
/blog/add - 请求方式 :
POST - 接口描述:用于新增一篇博客文章
请求参数
| 参数名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
userId |
Number | 是 | 发布用户ID |
title |
String | 是 | 博客标题 |
content |
String | 是 | 博客正文内容 |
请求示例
json
{
"userId": 1,
"title": "标题",
"content": "正文"
}
- 实现Controller 层
因为请求参数需要对应的实体类和数据库中对应的实体类不一致,因此需要额外处理一个接口实体类并进行数据转换。且保证接口对应实体属性不为空。
接口:
java
@PostMapping("/add")
public Result addBlogInfo(@Validated @RequestBody AddBlogRequest addBlogRequest){
log.info("发布博客,request:{}",addBlogRequest);
return Result.ok(blogService.addBlogInfo(addBlogRequest));
}
- 实现Service 层
java
@Override
public Boolean addBlogInfo(AddBlogRequest addBlogRequest) {
BlogInfo blogInfo = BeanTransUtils.transBlogInfo(addBlogRequest);
try {
blogInfoMapper.insert(blogInfo);
return true;
}catch (Exception e){
throw new BlogException("博客发布失败");
}
}
数据处理抽取为公共模块处理,代码和前两个章节中基本一致。
1.1 编辑器组件
发布博客使用的编辑器使用editor.md 进行编辑,是一个开源的页面markdown组件。
官网详见:http://editor.md.ipandao.com/
使用时引入对应依赖即可。
测试发布,结果可正常进行博文的发布:

二、实现修改博客
功能:当进入用户详情页时,如果当前登录用户正是文章作者,则在导航栏中显示编辑和删除按钮,点击进行对应处理。

- 约定前后端交互接口
基本信息
- 接口地址 :
/blog/update - 请求方式 :
POST - Content-Type :
application/json - 接口描述:用于更新一篇已存在的博客文章
请求参数
| 参数名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
id |
String | 是 | 博客文章ID |
title |
String | 是 | 博客标题 |
content |
String | 是 | 博客正文内容 |
请求示例
json
{
"id": "4",
"title": "测试修改文章",
"content": "在这里写下一篇博客"
}
- 实现 Controller 层
java
@PostMapping("/update")
public Boolean updateBlog(@Validated @RequestBody UpdateBlogRequest updateBlogRequest){
log.info("修改博客,request:{}",updateBlogRequest);
return blogService.updateBlog(updateBlogRequest);
}
- 实现Service 层
java
@Override
public Boolean updateBlog(UpdateBlogRequest updateBlogRequest) {
BlogInfo blogInfo = BeanTransUtils.transUpdateBlogInfo(updateBlogRequest);
try {
int i = blogInfoMapper.updateById(blogInfo);
return i==1;
}catch (Exception e){
throw new BlogException("博客更新失败");
}
}
数据转换同上。
在前端进行判断处理是否需要显示对应的编辑和删除按钮。
三、实现删除博客
- 约定前后端交互接口
基本信息
- 接口地址 :
/blog/delete - 请求方式 :
GET/POST - 接口描述:用于删除指定的博客文章
请求参数
| 参数名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
blogId |
Number | 是 | 要删除的博客ID |
请求示例
/blog/delete?blogId=1
- 实现Controller 层
java
@PostMapping("/delete")
public Boolean deleteBlog(@NotNull Integer blogId){
log.info("删除博客,blogId:{}",blogId);
return blogService.deleteBlog(blogId);
}
- 实现Service 层
java
@Override
public Boolean deleteBlog(Integer blogId) {
BlogInfo blogInfo = new BlogInfo();
blogInfo.setId(blogId);
blogInfo.setDeleteFlag(Constants.IS_DELETE);
try {
int i = blogInfoMapper.updateById(blogInfo);
return i==1;
}catch (Exception e){
throw new BlogException("博客删除失败");
}
}
验证测试发现博文可以正确被对应的用户作者删除。
四、加密/加盐
4.1 加密介绍
在MySQL数据库中,需要对密码,身份证号,手机号等敏感信息进行加密,以保证数据的安全性。
如果使用明文存储,当黑客入侵了数据库时,就可以轻松获取到用户的相关信息,从而对用户或者企业造成信息泄漏或者财产损失。
目前用户的密码还是明文设置的,为了保护用户的密码信息,需要对密码进行加密
4.2 密码算法分类
密码算法主要分为三类:对称密码算法,非对称密码算法,摘要算法。
-
对称密码算法 是指加密秘钥和解密秘钥相同的密码算法。常见的对称密码算法有:AES, DES, 3DES, RC4, RC5, RC6 等。
-
非对称密码算法 是指加密秘钥和解密秘钥不同的密码算法。该算法使用一个秘钥进行加密,用另外一个秘钥进行解密。
- 加密秘钥可以公开,又称为 公钥
- 解密秘钥必须保密,又称为 私钥
常见的非对称密码算法有:RSA, DSA, ECDSA, ECC 等
-
摘要算法 是指把任意长度的输入消息数据转化为固定长度的输出数据的一种密码算法。摘要算法是不可逆的,也就是无法解密。通常用来检验数据的完整性的重要技术,即对数据进行哈希计算然后比较摘要值,判断是否一致。常见的摘要算法有:MD5, SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16, CRC32)
根据上述也可以将密码算法分为两类:可逆密码算法和不可逆密码算法。
4.3 加密实现
问题:虽然经过MD5加密后的密文无法解密,但由于相同的密码经过MD5哈希之后的密文是相同的,当存储用户密码的数据库泄露后,攻击者会很容易便能找到相同密码的用户,从而降低了破解密码的难度。因此,在对用户密码进行加密时,需要考虑对密码进行包装,即使是相同的密码,也保存为不同的密文。即使用户输入的是弱密码,也考虑进行增强,从而增加密码被攻破的难度。
解决方案:采用为一个密码拼接一个随机字符来进行加密,这个随机字符我们称之为"盐"。假如有一个加盐后的加密串,黑客通过一定手段这个加密串,他拿到的明文并不是加密前的字符串,而是加密前的字符串和盐组合的字符串,这样相对来说又增加了字符串的安全性。
解密流程:MD5是不可逆的,通常采用"判断哈希值是否一致"来判断密码是否正确。
如果用户输入的密码,和盐值一起拼接后的字符串经过加密算法,得到的密文相同,我们就认为密码正确(密文相同,盐值相同,推测明文相同)

此处的Md5实现使用的是Spring 提供的工具类实现的。随机盐值使用UUID进行生成。
加密工具类:
java
public class Md5Utils {
/**
* Md5加密
*/
public static String enrypt(String password){
// 获取盐值
String salt = UUID.randomUUID().toString().replace("-","");
// 获取Md5密文
String secretPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
return salt+secretPassword;
}
/**
* 验证密码
*/
public static Boolean verify(String inputPassword,String sqlPassword){
if(!StringUtils.hasLength(sqlPassword)
||!StringUtils.hasLength(inputPassword)){
return false;
}
if(sqlPassword.length()!= Constants.MD5_LENGTH){
return false;
}
// 用户输入的密文
String salt = sqlPassword.substring(0,32);
String secretPassword = DigestUtils.md5DigestAsHex((salt+inputPassword).getBytes(StandardCharsets.UTF_8));
return sqlPassword.equals(salt+secretPassword);
}
}
使用测试类给密码123456进行密文的生成,32位密文与32位盐值组合在一起为存放的密文:d265f60759754a10af8f8228675f5ef4911d9c50298afddaa4dc49af0a353881
至此整个博客系统可以算是小成了,但还是有很多功能可以进行开发,不断完善。后续将会不断添加新的功能。