在几个月前实现了一个servlet版本的博客系统,本项目则是在原有基础上进行升级。使用SSM框架、数据库密码使用加盐算法加密、使用Redis对session进行持久化存储从而支持分部式部署、通过拦截器实现用户登录校验、对于数据格式返回以及异常处理进行统一功能处理、增加分页以及点击量统计等功能。
用户进入主页可以看到他人发布的博客,同时也可以注册账号通过本平台编写发布博客,平台支持markdown编辑;用户也可以在个人中心修改个人信息,同时对博客可以随写随存以草稿形式,之后也可以发布修改草稿。用户可以通过博客的点击量,判断博客质量等等。
1.前端开发:
技术:HTML、CSS、JavaScript
工具:IntelliJ IDEA 2021.3.1
2.后端开发:
服务器:tomcat-8.5.50
数据库:MySQL5.7
开发语言:Java
技术框架:SpringBoot、SpringMVC、Mybatis、Redis
管理工具:Maven
开发工具:Intellij IDEA 2020.1.4
操作系统:Windows10
Java源代码位于com.example.blog_system中;
在resources包中保存着系统资源,其中:
基于spring框架提供的md5加密的基础上通过UUID生成随机盐值,对用户密码进行加密;
加密过程如下:
//1.加盐并生成密码
public static String encrypt(String password){
//1.生成盐值
String salt = UUID.randomUUID().toString().replace("-","");
//2.生成加盐之后的密码
String saltpassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
//3。生成最终密码,32位盐值+"$"+加盐密码
String finalpassword = salt+"$"+saltpassword;
retur
在进行用户登录密码校验中,密码解密过程,从数据库取出密码,得到盐值,根据盐值以及用户输入密码进行加密,校验与数据库存储密码是否相同。
具体实现如下:
//2.生成最终密码(数据库中的,便于密码验证)
public static String encrypt(String password,String salt){
//2.通过盐值和原始密码生成加盐之后的密码
String saltpassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());
// 最终密码
String finalPassword = salt+"$"+saltpassword;
return finalPassword;
}
//3.验证密码
/**
*
* @param inputPassword 用户输入密码
* @param finalPassword 数据库存储密码
* @return
*/
public static boolean check(String inputPassword,String finalPassword){
//先进性非空校验和长度校验
if (StringUtils.hasLength(inputPassword)&&StringUtils.hasLength(finalPassword)
&&finalPassword.length()==65){
//1.得到盐值,从finalPassword,对$加上\\进行转义,它是关键字
String salt = finalPassword.split("\\$")[0];
//2.使用之前加密步骤将明文加密并生成最终密码
String confinmrPassword = PasswordUtils.encrypt(inputPassword,salt);
//3,进行比较
return confinmrPassword.equals(finalPassword);
}
return false;
}
定义数据格式为状态码+状态码描述信息+返回数据,实现成功以及失败的返回。
具体实现如下:
package com.example.blog_system.common;
import lombok.Data;
import java.io.Serializable;
/**
* 统一数据格式返回
*/
@Data
public class AjaxResult implements Serializable {
// 状态码
private Integer code;
// 状态码描述信息
private String msg;
// 返回的数据
private Object data;
/**
* 操作成功返回的结果
*/
public static AjaxResult succecc(Object data) {
AjaxResult result = new AjaxResult();
result.setCode(200);
result.setMsg("");
result.setData(data);
return result;
}
public static AjaxResult succecc(int code, Object data) {
AjaxResult result = new AjaxResult();
result.setCode(code);
result.setMsg("");
result.setData(data);
return result;
}
public static AjaxResult succecc(int code, String msg, Object data) {
AjaxResult result = new AjaxResult();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
/**
* 返回失败结果
*/
public static AjaxResult fail(int code, String msg) {
AjaxResult result = new AjaxResult();
result.setCode(code);
result.setMsg(msg);
result.setData(null);
return result;
}
public static AjaxResult fail(int code, String msg, Object data) {
AjaxResult result = new AjaxResult();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
}
继承HandlerInterceptor实现一个登录拦截器,判断在用户进入主页、登录页、注册页、以外的页面进行相关操作时判断是否登录,未登录则自动跳转到登录页面。
具体实现如下:
/**登录拦截器
* @author zq
* @date 2023-07-22 22:33
*/
public class LoginIntercept implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if(session!=null&&session.getAttribute(AppVariable.USER_SESSION_KEY)!=null){
//用户已登录
return true;
}
//跳转到登录页面
response.sendRedirect("/login.html");
return false;
}
}