解析博客系统后端实现

登录博客:博客登陆页

我的论坛系统:学生论坛 - 用户登录 论坛功能会断丰富,并接入AI,拭目以待!

1. 运用的框架和依赖

Spring Boot、Spring MVC、Mybatis-plus、lombok、JWT

2. 运用的主要技术

编程web接口、统一异常处理、统一数据返回、拦截器、Spring IOC 和 Spring DI 、Slf4j(lombok)、JWT令牌技术、Md5加密、加盐

3.项目分层

  1. 主体是"三层架构",即表现层业务逻辑层数据层
  2. 主体下还有,配置层公共层实体层

4.实现的功能

前端、后端和数据库三部分联动;前端发送合法请求,通过拦截器到达接口;发送非法请求则被拦截。

  1. 用户登录,输入账号和密码,后端获取数据库数据进行校验,校验通过则生成Token,并返回含有Token和登录用户Id的响应。
  2. 强制登录,(排除拦截 登录接口前端页面)拦截器判断请求中是否包含登录后设定的Token。没有Token,响应状态码就设定为401,前端收到401响应,则跳转到登录页面
  3. 获取博客列表,把数据库中所有的博客文章返回给前端。(别人写的博客也一并显示罗列)
  4. 获取博客详情,从数据库单独获取一篇博客返回给前端,如果登录用户和博客作者是同一个人则显示 "编辑" 和 "删除"。
  5. 添加博客,前端把作者Id、标题和博客内容数据发送给后端,后端使用SQL存入MySQL数据库。
  6. 修改博客,后端接收博客Id、标题和内容数据,通过SQL修改数据库数据。
  7. 删除博客,后端接收一个id,SQL根据id逻辑删除博客。
  8. 获取用户信息,博客列表页获取和显示登录用户信息,信息包含用户id、用户名和用户给GitHub地址。
  9. 获取作者信息,博客详情页显示博客作者信息,获取和显示的信息与"获取用户信息"接口返回信息类型的一致。

5.数据库设计

  1. 根据功能分析,项目主要围绕"用户 "和"博客 "两个名词,因此建立数据库blog_spring,数据库中创建用户表user_info和博客表blog_info。
  2. 客观分析,用户表最基本应有字段:1.id、2.用户名、3.登录密码、4.用户注销状态、5.用户信息创建时间、6.用户信息修改时间,除此之外,可适当添加字段丰富功能,我还添加了7."github地址字段"。(后续表中字段不足以支持功能实现,可以再添加)

|-----------------------|---------------------------|
| id | primary key |
| user_name(用户名) | not null |
| password(密码) | not null |
| github_url | 可为空 |
| delete_flag(用户注销状态) | default 0(0-未注销 1-注销) |
| create_time(用户信息创建时间) | CURRENT_TIMESTAMP(自动生成时间) |
| update_time(用户信息修改时间) | CURRENT_TIMESTAMP(自动生成时间) |
[用户表设计]

  1. 客观分析,博客表最基本应有字段:1.id、2.标题、3.正文内容、4.所属作者、5.博客删除状态、6.博客信息创建时间、7.博客信息修改时间。

|-----------------------|---------------------------|
| id | primary key |
| title(标题) | 可为空 |
| content(正文内容) | 可为空 |
| user_id(作者id) | 可为空 |
| delete_flag(博客删除状态) | default 0(0-未删除 1-删除) |
| create_time(博客信息创建时间) | CURRENT_TIMESTAMP(自动生成时间) |
| update_time(博客信息修改时间) | CURRENT_TIMESTAMP(自动生成时间) |
[博客表]

(解释,博客表的title、content和user_id明显不能为空,但我的数据库设计还是null,是因为我明确我在后端代码一定会对这三个属性进行非空校验。当然设置为 not null,也没问题)

6. 博客系统UML图展示

这个UML图是正常进行登录后,获取了Token的前提下,正常访问的流程。

没有正常登录获取不到Token,在访问后端接口时被拦截器拦截。

Flowchart Maker & Online Diagram Software

7.Java后端技术难点

7.1 加盐

计算机中的"加盐",这个"盐"指的是盐值。 盐值也就是一串随机生成的字符串。

"加盐"指的是,在用户自定义的密码基础上随机添加一串字符串,让用户的密码变得健壮一点,防止某些用户(如老人,小孩)因密码过于简单而被破解。加盐后的密码会进行加密,然后再存储到数据库中。加密再放入数据库,是为了防止被别人脱库后直接看到用户信息。


盐值的生成方式有多种,但只要保证每次生成的盐是随机的就行。

我使用Java原生的UUID生成盐值:

java 复制代码
import java.util.UUID;


public static String encryption(String password){
        //随机生成一个盐值
        String salt = UUID.randomUUID().toString().replace("-","");
        //加密--》(salt+password),下面这一条语句是加密
        String sqlPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
        return salt+sqlPassword;
    }

UUID生成的是带四个"-"的36位字符(如,92f43d09-eec1-4e47-94e7-41f37eff45a0),因此使用replace("-","")把-换成"",相当于剔除了某些字符变成32位十六进制的字符。

7.2 摘要算法

密码算法分为三种,1."对称密码算法",2."非对称密码算法",3."摘要算法"。

常见的摘要算法有:MD5,SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16,CRC32)

摘要算法是不可逆的,也就是加密后不能解密回去(MD5最好不要用在高安全环境),而对称和非对称密码算法可加密/解密。

7.2.1 MD5算法

博客系统采用MD5加密密码(用户密码+salt(盐)),加密后的明文,变成密文。


实现MD5的API有很多,像Spring、Hutool等都封装了MD5算法。

MD5加密后输出的密文存在两种,第一种:输出16位十六进制的字符;第二种:输出32位十六进制的字符。(其中,每一种又有大小写的版本,不过大小写之分不重要)

7.3 如何校验用户输入的密码

7.3.1 密码存入数据库

密码 ,非彼用户输入的密码(设用户密码为inputPassword),而是加密(inputPassword+salt)后得到的密文,密文再拼接salt存入数据库。

由于密文和盐值都是一堆字符,别人分不清哪堆是盐,哪堆是密码加密后的密文,所以开发人员随意把它们两任意拼接 后存入一个字段(我的拼接方式是直接:salt+密文)。加密后放入数据库,是为了防止被别人脱库后看到用户信息。

任意拼接的意思:

7.3.2 校验用户输入的密码是否正确

因为摘要算法不能解密,因此我们把输入的密码和数据库中存的密码进行比较,就能知道是否正确。当然用户输入的密码是明文,数据库存的是密文,直接校验肯定失败。开发人员肯定知道密文和salt的拼接规则。这时只要根据规则,就能从数据库中的密码解出salt。

这时加密(inputPassword+salt),得到密文,(salt+密文).equals(数据库密码)=》返回true 密码正确,返回false 密码错误。

注意:(salt+密文).equals(...)中的salt+密文的拼接方式必须和存入数据库时的拼接方式一样。

7.4 JWT令牌技术

7.4.1介绍JWT令牌

JSON Web Tokens - jwt.io

令牌本质就是字符串,实现它的方式有很多,JWT就是其中之一。

JWT全称:JSON Web Token.

JWT组成:

  1. Header (头部)包含令牌类型(即JWT),及使用的哈希算法(如HMAC SHA256或RSA)。
  2. Payload(负载)包含自定义的有效信息,比如{"userName":"123","userAge":"12"},也含有时间信息等。
  3. Signature(签名)此部分用于防止JWT被篡改,确保安全性。

下图左侧是JWT令牌,右侧是JWT解码后的数据信息:

右边三部分也就是"头部"、"负载"和"签名",是左边解码后得出来的。相应的,左边的JWT是右边三部分编码后等到的。JWT令牌被两个"."分隔开,每个部分颜色都不同,第一部分解码后对应header;第二部分的紫色解码对应payload;需要注意的是,第三部分是通过自己设定256位的密码,再配合上前面两部分的base64编码,经过自己选定的签名算法加密得出来的值,值再经过base64编码后得出来的。

文字看的一头雾水的可直接看下图:

7.4.2 JWT令牌的用处

我们知道Cookie中存储SeesionId是为了,保证用户的隐私(session)只被自己使用和方便访问多个页面。

JWT也类似,客户端在登录时输入用户名和密码后,服务端则会返回一个独有的JWT。之后用户每次发送的请求都会带上JWT,服务端只有校验JWT内容没被修改,且信息正确才会进行后续操作。操作图如下:

java 复制代码
@Test
    void genToken(){
        //要输入>=256位的数据生成,自定义key,但"123456"小于256位会导致报错
//        Key key = Keys.hmacShaKeyFor("123456".getBytes(StandardCharsets.UTF_8));
        //用HS256签名算法,随机生成一个密钥
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        //可使用Map作为令牌载荷
        Map<String,Object> map = new HashMap<>();
        map.put("name","哈利波特");
        map.put("age",15);
        //生成令牌
        String compact = Jwts.builder()
                .setClaims(map)
                //签名使用密钥生成,一种密钥生成一种签名字符串
                .signWith(key)
                .compact();
        System.out.println(compact);

                                                //传入key
        JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();
        /*
            验证令牌:使用密钥校验签名的有效性。
            JWT令牌的签名验证过程,本质上就是‌服务端使用同一个密钥重新生成一个签名,然后与令牌中携带的签名进行比对‌
            如果签名不匹配(数据被篡改)或密钥错误,会抛出异常(如 SignatureException),表示令牌不可信。
         */
        System.out.println("111"+build.parse(compact).getBody());
        System.out.println("222"+build.parseClaimsJws(compact).getBody());
    }

(总的来说,JWT的核心是防伪,这一点和"证书"类似。)

8.博客系统简述

  1. 没设计用户注册功能
  2. 登录用户只有两个,第一个 zhangsan 密码123456;第二个 lisi 密码 123456
  3. 主页面展示所有未删除博客;主页面显示登录用户信息
  4. 点入任何一篇博客,如果博客是登录用户写的,则显示"编辑"和"删除"
  5. 编辑博客,点击编辑,跳转到修改页面,页面填充标题和正文,编辑方式采用markdown
  6. 删除博客,点击即删除
  7. 写博客,采用markdown格式
  8. 注销,这里的注销是退出,并不是注销用户
  9. 主页,处于任何页面,点击主页按钮,立马跳转至主页

博客系统,是我第一个部署上云服务的项目,虽然项目很简陋,但学有所用的感觉很开心!

相关推荐
笨蛋不要掉眼泪1 小时前
RabbitMQ消息队列:交换机机制
java·分布式·rabbitmq
米码收割机2 小时前
【项目】spring boot+vue3 宠物领养系统(源码+文档)【独一无二】
java·spring boot·宠物
刹那芳华19923 小时前
STMF+ESP-S+MQTT协议连接华为云端(附踩坑记录)
java·struts·华为
就改了8 小时前
Java8 日期处理(详细版)
java·python·算法
麻瓜生活睁不开眼9 小时前
Android16定制SearchLauncher新增投屏Cast桌面快捷图标完整实现
java·launcher·aosp16
IT小盘10 小时前
12-Prompt不等于一句话-System-User-Context三层结构
java·windows·prompt
都叫我大帅哥11 小时前
Spring Data JPA 查询之道:方法命名与示例查询完全指南
java·后端·spring
momo12 小时前
Java+WebAI黑马知识点
java·spring boot·mybatis
重庆小透明13 小时前
带你从不同视角了解三大MQ
java·学习·spring·kafka·rabbitmq·rocketmq