基于Spring实现博客项目

访问地址: 用户登录

代码获取 :基于Spring实现博客项目: Spring项目写博客项目

一.项目开发

1.项目开发阶段

  1. 需求评审,需求分析
  2. 项目设计(接口设计,DB设计等,比较大的需求,需要设计流程图,用例图,UML, model中的字段)
  3. 开发+自测
  4. 提测(提交测试)
  5. 验收:预发布环境/预生产环境部署测试(开发,测试,产品)
  6. 上线

2.前端页面

1.登录页面: 根据用户名和密码,进行登录

2.博客列表页:显示所有博客列表,以及显示登录用户的个人信息 3.博客详情页:显示当前博客的详细信息,以及作者信息

4.博客插入/编辑页

3.需求分析

1.登录接口(根据用户名和密码,来判断是否登录成功) 2.根据用户ID,获取用户相关信息

3.获取所有的博客列表

4.根据博客ID,获取博客的详情信息(作者ID) 5.根据博客ID,更新博客内容

6.插入博客

7.删除博客

4.数据库设计

sql 复制代码
        --建表sql
        create database if not exists `java_blog_spring` charset utf8mb4;
        --用户表
        drop table if exists `java_blog_spring`.`user`;
        create table `java_blog_spring`.`user` (
        `id` int not null auto_increment,
        `user_name` varchar(128) not null,
        `password` varchar(128) not null,
        `github_url` varchar(128) null,
        `delete_flag` tinyint(4) null default 0,
        `create_time` timestamp null default current_timestamp(),
        primary key (`id`),
        unique index `user_name_unique` (`user_name` asc))
        engine = innodb default character set = utf8mb4 comment = '⽤户表';
        --博客表
        drop table if exists `java_blog_spring`.`blog`;
        create table `java_blog_spring`.`blog` (
        `id` int not null auto_increment,
        `title` varchar(200) null,
        `content` text null,
        `user_id` int(11) null,
        `delete_flag` tinyint(4) null default 0,
        `create_time` timestamp null default current_timestamp(),
        primary key (`id`))
        engine = innodb default charset = utf8mb4 comment = '博客表';
        --新增用户信息
        insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url`)
        values("zhangsan","123456","https://gitee.com/bubble-fish666/class-java4
        5");
        insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
        `)values("lisi","123456","https://gitee.com/bubble-fish666/class-java45");
        insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
        ("第一篇博客","111我是博客正文我是博客正文我是博客正文",1);
        insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
        ("第二篇博客","222我是博客正文我是博客正文我是博客正文",2);

二.Java项目

1.创建Spring项目

创建好之后为以下页面

2.创建实体类

用户实体类

java 复制代码
@Data
public class User {
    private Integer id;
    private String userName;
    private String password;
    private String githubUrl;
    private Byte deleteFlag;
    private Date createTime;
}

博客实体类

java 复制代码
@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Byte deleteFlag;
    private Date createTime;
}

3.创建Mapper

userMapper.java

java 复制代码
@Mapper
public interface UserMapper {
    @Select("select * from user where id=#{id}")
    User selectById(Integer id);
    @Select("select * from user where user_name=#{name}")
    User selectByName(String name);
}

userMapper.xml

Groovy 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javastudy.blog_spring.mapper.UserMapper">



</mapper>

blogMapper.java

java 复制代码
@Mapper
public interface BlogMapper {
    @Select("select * from blog where delete_flag=0")
    List<Blog> selectAll();

    @Select("select * from blog where id=#{id} and delete_flag=0")
    Blog selectById(Integer id);

    Integer updateBlog(Blog blog);
    @Insert("insert into blog(content,title,user_id) values(#{content},#{title},#{userId})")
    Integer insertBlog(Blog blog);
}

blogMapper.xml

Groovy 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javastudy.blog_spring.mapper.BlogMapper">

    <update id="updateBlog">
        update blog
        <set>
            <if test="title!=null">title=#{title},</if>
            <if test="content!=null">content=#{content},</if>
            <if test="userId!=null">user_id=#{userId},</if>
            <if test="deleteFlag!=null">delete_flag=#{deleteFlag},</if>

        </set>
            where id=#{id};
    </update>


</mapper>

4.配置文件

application.yml

Groovy 复制代码
spring:
  profiles:
    active: dev

# 日志信息
logging:
  file:
    path: logs/
  level:
    root: info

application-dev.yml

Haskell 复制代码
server:
  port: 8080


# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://localhost:13306/java_blog_spring?characterEncoding=utf8&useSSL=false
    username: root
    password: woaini520
    driver-class-name: com.mysql.cj.jdbc.Driver

#  mybatis xml 配置路径
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true  #驼峰转换

application-prod.yml

Haskell 复制代码
server:
  port: 8080


# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/java_blog_spring?characterEncoding=utf8&useSSL=false
    username: root
    password: woaini520
    driver-class-name: com.mysql.cj.jdbc.Driver

#  mybatis xml 配置路径
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  configuration:
    map-underscore-to-camel-case: true

5.测试类

userMapper

java 复制代码
@SpringBootTest
@Slf4j
class UserMapperTest {
    @Autowired
    UserMapper userMapper;

    @Test
    void selectById() {
        User user = userMapper.selectById(1);
        log.info(user.toString());
    }

    @Test
    void selectByName() {
        User user = userMapper.selectByName("zhangsan");
        log.info(user.toString());
    }
}

blogMapper

java 复制代码
@SpringBootTest
@Slf4j
class BlogMapperTest {
    @Autowired
    BlogMapper blogMapper;

    @Test
    void selectAll() {
        List<Blog> blogs = blogMapper.selectAll();
        log.info(blogs.toString());

    }

    @Test
    void selectById() {
        Blog blog = blogMapper.selectById(1);
        log.info(blog.toString());
    }

    @Test
    void updateBlog() {
        Blog blog = new Blog();
        blog.setId(1);
        blog.setTitle("测试的第一篇博客");
        blog.setTitle("测试的第一篇博客的正文内容");
        blogMapper.updateBlog(blog);
    }

    @Test
    void insertBlog() {
        Blog blog = new Blog();
        blog.setTitle("第三篇博客");
        blog.setContent("第三篇博客的正文内容");
        blog.setUserId(1);
        blogMapper.insertBlog(blog);
    }
}

6.Common包

1.Result

java 复制代码
@Data
public class Result {
    //业务处理状态码 200成功 <=0表示失败  (注意与请求状态码区分)
    private Integer code;
    //业务返回信息
    private String msg;
    //业务数据
    private Object data;


    /**
     * 业务处理失败
     *
     * @param code
     * @param message
     * @return
     */
    public static Result fail(Integer code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(message);
        result.setData("");

        return result;
    }

    public static Result fail(Integer code, String message, Object data) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(message);
        result.setData(data);

        return result;
    }

    public static Result success(Object data) {
        Result result = new Result();
        result.setCode(200);
        result.setMsg("");
        result.setData(data);

        return result;
    }

    public static Result success(String message, Object data) {
        Result result = new Result();
        result.setCode(200);
        result.setMsg(message);
        result.setData(data);

        return result;
    }

}

2.ErrorAdvice(统一异常返回)

java 复制代码
@ControllerAdvice
public class ErrorAdvice {
    @ExceptionHandler
    public Result error(Exception e) {

        return Result.fail(-1, e.getMessage());

    }
}

3.统一返回格式处理

java 复制代码
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Result) {
            return body;
        }
        if (body instanceof String) {
            ObjectMapper objectMapper = new ObjectMapper();

            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }

}

7.导入前端代码

前端代码在这取:基于Spring实现博客项目: Spring项目写博客项目

三.业务代码

1.约定前后端交互接口

请求

/blog/getlist

响应

{ blogId: 1, title: "第⼀篇博客", content: "博客正⽂", userId: 1, postTime: "2021-07-07 12:00:00" }, { blogId: 2, title: "第⼆篇博客", content: "博客正⽂", userId: 1, postTime: "2021-07-07 12:10:00" },

UserService

java 复制代码
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BlogMapper blogMapper;

    public User selectById(Integer id) {
        return userMapper.selectById(id);
    }

    public User selectByName(String name) {
        return userMapper.selectByName(name);
    }

    public User getAuthorInfoByBlogId(Integer id) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null || blog.getUserId() < 0) {
            return null;
        }
        return userMapper.selectById(blog.getUserId());
    }
}

BlogService

java 复制代码
@Service
public class BlogService {
    @Autowired
    private BlogMapper blogMapper;

    public List<Blog> getAll() {
        return blogMapper.selectAll();
    }

    public Blog getBlogById(Integer id) {
        return blogMapper.selectById(id);
    }

    public Integer updateBlog(Blog blog) {
        return blogMapper.updateBlog(blog);
    }

    public Integer addBlog(Blog blog) {
        return blogMapper.insertBlog(blog);
    }

}

3.Controller层

BlogController

java 复制代码
@RestController
@RequestMapping("/blog")
public class BlogController {
    @Autowired
    BlogService blogService;

    @RequestMapping("/getlist")
    public List<Blog> getBlogList() {
        return blogService.getAll();

    }

    @RequestMapping("/getBlogDetail")
    public Result getBlogDetail(Integer id, HttpSession httpSession) {
        if (id == null || id < 0) {
            return Result.fail(-1, "非法的参数");
        }
        Blog blog = blogService.getBlogById(id);
        User user = (User) httpSession.getAttribute(Constants.USER_INFO_SESSION);

        if (blog.getUserId() == user.getId()) {
            blog.setIsLoginUser(true);
        }

        return Result.success(blog);

    }

    @RequestMapping("/add")
    public Result addBlog(String title, String content, HttpSession httpSession) {
        if (!StringUtils.hasLength(title) || !StringUtils.hasLength(content)) {
            return Result.fail(-1, "内容不能为空");
        }
        User user = (User) httpSession.getAttribute(Constants.USER_INFO_SESSION);
        if (user == null || user.getId() < 0) {
            return Result.fail(-1, "用户不存在");
        }
        Blog blog = new Blog();
        blog.setContent(content);
        blog.setTitle(title);
        blog.setUserId(user.getId());
        blogService.addBlog(blog);

        return Result.success(true);

    }

    @RequestMapping("/update")
    public Result updateBlog(Blog blog) {
        if (!StringUtils.hasLength(blog.getContent()) || !StringUtils.hasLength(blog.getTitle()) || blog.getId() == null) {
            return Result.fail(-1, "内容不能为空");
        }
        blogService.updateBlog(blog);

        return Result.success(true);

    }

    @RequestMapping("/delete")
    public Result deleteBlog(@RequestParam("id") Integer blogId) {
        if (blogId == null || blogId < 0) {
            return Result.fail(-1, "博客id不合法或者为空");
        }
        Blog blog = new Blog();
        blog.setId(blogId);
        blog.setDeleteFlag((byte) 1);
        blogService.updateBlog(blog);
        return Result.success(true);
    }
}

UserController

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping("/login")
    public Result login(HttpServletRequest request, String username, String password) {
        //参数校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return Result.fail(-2, "账号或密码不能为空");
        }
        //密码校验
        User user = userService.selectByName(username);
        if (user == null || !user.getPassword().equals(password)) {
            return Result.fail(-3, "用户名不存在或者密码错误");
        }

        //参数返回
        user.setPassword("");
        HttpSession session = request.getSession(true);
        session.setAttribute(Constants.USER_INFO_SESSION, user);

        return Result.success("登陆成功");
    }

    @RequestMapping("/getUserInfo")
    public Result getUserInfo(HttpSession session) {
        if (session == null || session.getAttribute(Constants.USER_INFO_SESSION) == null) {
            return Result.fail(-1, "用户未登录");
        }
        return Result.success(session.getAttribute(Constants.USER_INFO_SESSION));

    }

    @RequestMapping("/getAuthorInfo")
    public Result getAuthorInfoByBlogId(@RequestParam("id") Integer blogId) {
        if (blogId == null || blogId < 0) {
            return Result.fail(-1, "id参数错误");
        }
        User user = userService.getAuthorInfoByBlogId(blogId);
        if (user == null) {
            return Result.fail(-1, "不存在文章作者");
        }
        user.setPassword("");

        return Result.success(user);


    }

    @RequestMapping("/logout")
    public Result logout(HttpSession session) {
        session.removeAttribute(Constants.USER_INFO_SESSION);

        return Result.success(true);

    }
}

4.登录接口拦截器

java 复制代码
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(Constants.USER_INFO_SESSION) == null) {
            response.setStatus(401);
            return false;
        }
        return true;
    }
}
java 复制代码
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    private final List<String> excludes = Arrays.asList(
            "/**/*.html",
            "/blog-editormd/**",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/user/login"
    );

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).
                addPathPatterns("/**"). //拦截所有路径
                excludePathPatterns(excludes);
    }
}

在blog_list.html和blog_detail的ajax请求添加

javascript 复制代码
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }

四.前端代码

有些代码重复出现,可以抽象为一个函数,我们放在./js/common.js中

javascript 复制代码
function logout() {

    $("#logout").click(function () {
        $.ajax({
            type: "get",
            url: "/user/logout",
            success: function (result) {
                if (result != null && result.data == true) {
                    location.assign("/blog_login.html")
                }
            },
        })

    })
}

1.blog_list.html

先来个前置知识:日期格式化

方式一:将日期格式改为(java.sql.Date适用)

private Timestamp createTime;

然后引入js包

javascript 复制代码
function formatDate(time) {
    var date = new Date(time);

    var year = date.getFullYear(),
        month = date.getMonth() + 1,//月份是从0开始的
        day = date.getDate(),
        hour = date.getHours(),
        min = date.getMinutes(),
        sec = date.getSeconds();
    var newTime = year + '-' +
        (month < 10 ? '0' + month : month) + '-' +
        (day < 10 ? '0' + day : day) + ' ' +
        (hour < 10 ? '0' + hour : hour) + ':' +
        (min < 10 ? '0' + min : min) + ':' +
        (sec < 10 ? '0' + sec : sec);

    return newTime;
}

直接进行转化即可

javascript 复制代码
<script src="./js/common.js"></script>
formatDate(blog.createTime)

方式二:(java.util.Date适用)

工具类

java 复制代码
public class DateUtils {
    public static String formatDate(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(date);
    }
}

博客实体类

java 复制代码
@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Byte deleteFlag;
    private Date createTime;

    public String getCreateTime() {
        return DateUtils.formatDate(createTime);
    }
}

此时就不需要多余的操作了

javascript 复制代码
     finalHtml += '<div class="date">'+blog.createTime+'</div>';

之后javascrip代码

javascript 复制代码
    <script src="./js/jquery.min.js"></script>
    <script src="./js/common.js"></script>

    <script>
        $(function () {
            $.ajax({
                type: "get",
                url: "/blog/getlist",
                success: function (result) {
                    var finalHtml = "";
                    if (result.code == 200 && result.data != null && result.data.length > 0) {
                        var dataHtml = result.data;
                        for (var i = 0; i < dataHtml.length; ++i) {
                            var blog = dataHtml[i];
                            finalHtml += '<div class="blog">';
                            finalHtml += '<div class="title">' + blog.title + '</div>';
                            finalHtml += '<div class="date">' + blog.createTime + '</div>';
                            finalHtml += '<div class="desc">' + blog.content + '</div>';
                            finalHtml += '<a class="detail" href="blog_detail.html?id=' + blog.id + '">查看全文&gt;&gt;</a>';
                            finalHtml += '</div>';
                        }
                        $(".right").html(finalHtml);

                    }
                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

            $.ajax({
                type: "get",
                url: "/user/getUserInfo",
                success: function (result) {
                    if (result != null && result.code == 200 && result.data != null) {
                        $(".container .left .card h3").text(result.data.userName);
                        $(".container .left .card a").attr("href", result.data.githubUrl)
                    }

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

            logout();


        })

    </script>

2.blog_detail.html

javascript 复制代码
    <script src="./js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.js"></script>
    <script src="blog-editormd/lib/marked.min.js"></script>
    <script src="blog-editormd/lib/prettify.min.js"></script>
    <script src="js/common.js"></script>

    <script>
        $(function () {
            $.ajax({
                type: "get",
                url: "/blog/getBlogDetail" + location.search,
                success: function (result) {
                    if (result.code == 200 && result.data != null) {
                        var blog = result.data;
                        $(".title").text(blog.title);
                        $(".date").text(blog.createTime);
                        editormd.markdownToHTML("content", {
                            markdown: blog.content,
                        });

                        if (result.data.isLoginUser == true) {
                            var innerhtml = "";
                            innerhtml += '<button onclick="window.location.href = \'blog_update.html?id=' + blog.id + '\'">编辑</button>';
                            innerhtml += '<button onclick="deleteBlog()">删除</button>';
                            $(".operating").html(innerhtml);
                        }
                    }

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });
            $.ajax({
                type: "get",
                url: "/user/getAuthorInfo" + location.search,
                success: function (result) {
                    if (result != null && result.code == 200 && result.data != null) {
                        $(".container .left .card h3").text(result.data.userName);
                        $(".container .left .card a").attr("href", result.data.githubUrl)
                    }

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

            // jQuery("#deleteButton").click(function () {
            //     if (confirm("确定要删除吗?")) {
            //         $.ajax({
            //             type: "post",
            //             url: "/blog/delete" + location.search,
            //             success: function (result) {
            //                 if (result != null && result.data == true) {
            //                     location.assign("blog_list.html");
            //                 }
            //             }

            //         })
            //     }

            // });


        })
        function deleteBlog() {
            if (confirm("确定要删除吗?")) {
                $.ajax({
                    type: "post",
                    url: "/blog/delete" + location.search,
                    success: function (result) {
                        if (result != null && result.data == true) {
                            location.assign("blog_list.html");
                        }
                    }

                })
            }

        };
        logout();


    </script>

3.blog_login.html

javascript 复制代码
    <script src="./js/jquery.min.js"></script>
    <script>
        $(function () {

            $("#submit").click(function () {
                //获取用户名
                var username = jQuery("#username");
                if (!username.val()) {
                    alert("用户名不能为空");
                    username.focus();
                    return;
                }

                //获取密码
                var password = jQuery("#password");
                if (!password.val()) {
                    alert("密码不能为空");
                    password.focus();
                    return;
                }


                $.ajax({
                    type: "post",
                    url: "/user/login",
                    data: {
                        username: username.val(),
                        password: password.val()
                    },
                    success: function (result) {
                        if(result.code==200){
                            //跳转到主页
                            location.href="blog_list.html";
                            return;
                        }else{
                            //业务处理失败
                            alert(result.msg);
                            return;
                        }
                        
                    },
                    error: function () {

                    }
                })

            })


        })
        
    </script>

4.blog_edit.html

javascript 复制代码
    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.min.js"></script>
    <script type="text/javascript">

        $(function () {
            var editor = editormd("editor", {
                width: "100%",
                height: "550px",
                path: "blog-editormd/lib/"
            });

            $("#submit").click(function () {
                $.ajax({
                    type: "post",
                    url: "/blog/add",
                    data: {
                        title: $("#title").val(),
                        content: $("#content").val()
                    },
                    success: function (result) {
                        if (result != null && result.data != null && result.data == true) {
                            location.assign("blog_list.html");

                        }

                    },
                    error: function (result) {
                        if (result != null && result.status == 401) {
                            alert("请登录之后再进行操作");
                        }

                    }
                })
            })


        });
    </script>

5.blog_update.html

javascript 复制代码
    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.min.js"></script>
    <script src="js/common.js"></script>
    <script type="text/javascript">

        $(function () {
            var editor = editormd("editor", {
                width: "100%",
                height: "550px",
                path: "blog-editormd/lib/"
            });

            $.ajax({
                type: "get",
                url: "/blog/getBlogDetail" + location.search,
                success: function (result) {
                    var blog = result.data;
                    if (result != null && result.code == 200 && result.data != null) {
                        $("#title").val(blog.title);
                        $("#content").val(blog.content);
                        $("#blogId").val(blog.id);
                    }

                },
                error: function (result) {
                    if (result != null && result.status == 401) {
                        alert("请登录之后再进行操作");
                    }

                }

            });
            $("#submit").click(function () {
                $.ajax({
                    type: "post",
                    url: "/blog/update",
                    data: {
                        title: $("#title").val(),
                        content: $("#content").val(),
                        id: $("#blogId").val()
                    },
                    success: function (result) {
                        if (result != null && result.data == true) {
                            location.assign("blog_list.html");
                        }

                    },
                    error: function (result) {
                        if (result != null && result.status == 401) {
                            alert("请登录之后再进行操作");
                        }

                    }
                })
            })

        });

    </script>

五.加密措施

1.加密

假设我们的数据库被黑客进行劫持,那么用户的一些重要信息(比如密码,身份证号)就可能被获取,这样对用户是十分不利的,因此我们需要对数据库中一些重要的信息进行加密存储.

目前有许多的加密算法,包括可逆加密和非可逆加密,可逆加密在http和https的时候就有使用,通过密钥就可以使明文变为密文,同时也可以让密文变为明文,但是非可逆加密就不同了,非可逆加密只能使明文加密为密文,不能从密文变为明文,一般在数据库中我们采用非可逆加密.

常用的非可逆加密有MD5加密,通过对明文加密,可以得到长度固定的MD5值,MD5加密就可以得到32位或者16位的加密后的结果.

Java中使用MD5加密

java 复制代码
@SpringBootTest
class BlogSpringApplicationTests {

    @Test
    void contextLoads() {
        String finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第一次加密:" + finalPassword);
        finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第二次加密:" + finalPassword);
        finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第三次加密:" + finalPassword);
    }

}

可以观察到:MD5加密后得到的值是都是一样的,并且无论进行多少次MD5加密(对产生的MD5值多次进行加密),得到的结果都是一样的.

那么这样会不会产生安全问题呢?当然会!虽然说MD5加密是不可逆的加密,但是可以通过提前生成对应的明文和密文对应的表,然后通过需要破解的密文与之前生成表的密文进行对应,从而找到相应的明文,但是这种方法是十分低效的,但是也可以进行破解明文,尤其对于密码不复杂且短的很容易破解,那么怎么样可以避免这种情况呢?

首先可以在用户端进行,我们在设置的密码的时候,通常网站都要求需要字母与数字的组合,并且长度都要求大于一定的值,这样密码的安全等级很高,不容易被破解,(比如纯数字组合就10种,字母加数字就有26+10种,大小写字母加数字组合就有26*2+10种,长度越长组合自然也就越多).

接下来通过服务端通过加盐的方式存储密码.

2.盐值

假设用户的密码安全很低,如果在存储的时候将密码与随机的字符串的进行拼接,然后再通过MD5加密的方式进行存储的话,同样也可以时密码难以破解,并且可以通过生成多个不同的随机字符串,可以解决MD5不能实现多次加密的问题.随机生成的字符串也要存储到数据库中,通常与生成的MD5数值拼接存储.

代码展示,通过UUID生成随机的字符串.

java 复制代码
    @Test
    void contextLoads() {
        String salt = UUID.randomUUID().toString();
        String finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第一次salt:" + salt);
        System.out.println("第一次加密:" + finalPassword);
        salt = UUID.randomUUID().toString();
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第二次salt:" + salt);
        System.out.println("第二次加密:" + finalPassword);
        salt = UUID.randomUUID().toString();
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第三次salt:" + salt);
        System.out.println("第三次加密:" + finalPassword);
    }

我们不希望产生的salt含有特殊字符,因此我们可以通过以下的方式将"-"去掉

java 复制代码
    @Test
    void contextLoads() {
        String salt = UUID.randomUUID().toString().replace("-", "");
        String finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第一次salt:" + salt);
        System.out.println("第一次加密:" + finalPassword);
        salt = UUID.randomUUID().toString().replace("-", "");
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第二次salt:" + salt);
        System.out.println("第二次加密:" + finalPassword);
        salt = UUID.randomUUID().toString().replace("-", "");
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第三次salt:" + salt);
        System.out.println("第三次加密:" + finalPassword);
    }

3.实现

java 复制代码
public class SecurityUtils {

    /**
     * 将密码进行加密
     * 根据明文,返回密文(salt+MD5)
     *
     * @param password
     * @return
     */
    public static String encry(String password) {
        //生成盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        //进行加密
        String finalPassword = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        return salt + finalPassword;

    }

    /**
     * @param inputPassword 输入的密码
     * @param finalPassword 数据库存储的密码
     * @return 输入的密码和存储的密码是否相同
     */
    public static boolean decrypt(String inputPassword, String finalPassword) {
        if (!StringUtils.hasLength(inputPassword) || !StringUtils.hasLength(finalPassword)) {
            return false;
        }
        if (finalPassword.length() != 64) {
            return false;
        }
        String salt = finalPassword.substring(0, 32);
        String password = DigestUtils.md5DigestAsHex((inputPassword + salt).getBytes());
        return (salt + password).equals(finalPassword);


    }


}

修改密码验证的接口

java 复制代码
    @RequestMapping("/login")
    public Result login(HttpServletRequest request, String username, String password) {
        //参数校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return Result.fail(-2, "账号或密码不能为空");
        }
        //密码校验
        User user = userService.selectByName(username);
        if (user == null || !SecurityUtils.decrypt(password, user.getPassword())) {
            return Result.fail(-3, "用户名不存在或者密码错误");
        }

        //参数返回
        user.setPassword("");
        HttpSession session = request.getSession(true);
        session.setAttribute(Constants.USER_INFO_SESSION, user);

        return Result.success("登陆成功");
    }

六.上线发布

1.多平台开发

XML 复制代码
    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <env>dev</env>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <env>prod</env>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
        </profile>
    </profiles>

如果需要跳过test,可以点击

application.yml文件

此时打包即可

2.部署linux服务器

1.创建数据库

可以将sql语句变成一个文件,然后执行下面的

source /root/java78/create.sql

2.将代码打包

打包完成之后,将jar包拖拽到linux服务器上

3.运行代码

后台启动项目

nohup java -jar Blog_Spring-0.0.1-SNAPSHOT.jar &

查看日志

cd logs/

tail -f spring.log

终止当前的服务

ps -ef | grep [ ]

注意:如果开启多个服务,需要开端口,给防火墙添加端口号

查看防火墙状态(如果没开启,建议开启,不开启可以直接访问,开启了需要进行已下的操作访问)

systemctl status firewalld

启动防火墙和关闭防火墙

systemctl start firewalld

systemctl stop firewalld

查看开放的端口号

firewall-cmd --list-ports

开启8080端口

firewall-cmd --permanent --add-port=8080/tcp

重启防火墙

firewall-cmd --reload

设置开机启动

systemctl enable firewalld

添加安全组

否则无法正常访问

相关推荐
这里有鱼汤21 分钟前
别傻了,这些量化策略AI 10 秒就能帮你写好
后端·python
坐观垂钓者22 分钟前
使用EasyExcel 导出复杂的合并单元格
java·excel
Victor3562 小时前
Redis(16)Redis的有序集合(Sorted Set)类型有哪些常用命令?
后端
Victor3562 小时前
Redis(17)如何在Redis中设置键的过期时间?
后端
22jimmy2 小时前
JavaWeb(二)CSS
java·开发语言·前端·css·入门·基础
vvilkim5 小时前
Java主流框架全解析:从企业级开发到云原生
java·运维·云原生
MZ_ZXD0016 小时前
springboot汽车租赁服务管理系统-计算机毕业设计源码58196
java·c++·spring boot·python·django·flask·php
A 计算机毕业设计-小途7 小时前
大四零基础用Vue+ElementUI一周做完化妆品推荐系统?
java·大数据·hadoop·python·spark·毕业设计·毕设
岁忧9 小时前
(nice!!!)(LeetCode 每日一题) 679. 24 点游戏 (深度优先搜索)
java·c++·leetcode·游戏·go·深度优先
你的人类朋友10 小时前
说说git的变基
前端·git·后端