项目9-网页聊天室1(注册+Bycrpt加密)

1.准备工作

1.1.前端页面展示 

1.2 数据库的建立 

我们通过注册页面,考虑如何设计用户表数据库。

  1. 用户id,userId
  2. 用户名,唯一,username
  3. 用户密码,password(包括密码和确认密码ensurePssword【数据库没有该字段】)
  4. 同时还需要考虑是否需要将图片和用户进行分离

                //我考虑的是将其合并在一起

                //这样做的好处是直接和userId相对应

                //省去了其余的操作

      5.需要存储图片名字(picname)

      6.需要存储图片地址(path)

-- 数据库
drop database if exists `chatroom`;
create database if not exists `chatroom` character set utf8;
-- 使用数据库
use `chatroom`;

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userId` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(200) NOT NULL,
`password` varchar(200) NOT NULL,
`picname` varchar(200) NOT NULL,
`path` varchar(255) NOT NULL
);

2.前端代码 

2.1 model

@Data
public class User {
    private Integer userId;
    private String username;
    private String password;
    private String picname;
    private String path;
}

2.2 service

package com.example.demo.service;

import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;


@org.springframework.stereotype.Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public Boolean insertUserInfo(String username,String password,String picname,String path){
        Integer influncefactor=userMapper.insertUserInfo(username,password,picname,path);
        if(influncefactor>0){
            return true;
        }
        return false;
    }

}

2.3 controller

package com.example.demo.controller;

import com.example.demo.config.AppConfig;
import com.example.demo.config.Result;
import com.example.demo.constant.Constant;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @RequestMapping("/register")
    public Result registerUser(@RequestParam MultipartFile file,String username,String password,String ensurePassword){
        //当旧密码与新密码所输入的一样,且都不为空才会进行后续操作
        if(!StringUtils.hasLength(username)||!StringUtils.hasLength(password)||!StringUtils.hasLength(ensurePassword)){
            return Result.fail(Constant.RESULT_CODE_MESSAGENULL,"你所输入的信息为空,违规");
        }
        //两个密码必须一致才可以进行后续操作
        if(!password.equals(ensurePassword)){
            return Result.fail(Constant.RESULT_CODE_NOTSAMEPASSWORD,"两次密码输入不一致,违规");
        }
        String fileName=file.getOriginalFilename();
        String path = Constant.SAVE_PATH +fileName;
        File dest=new File(path);
        //图片可以是同一张图片
        //直接上传图片
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail(Constant.RESULT_CODE_UPLOADPICFAIL,"图片上传失败");
        }
        //同时要将密码进行加密BCrypt
        String newpassword=bCryptPasswordEncoder.encode(password);
        //将所输入的数据存入数据库中
        if(userService.insertUserInfo(username,newpassword,fileName,path)){
            return Result.success(true);
        }
        return Result.fail(Constant.RESULT_CODE_FAIL,"上传数据库失败");
    }
}

3.前端接口测试

每个if语句都需要判断一次

3.1 成功情况

3.2 用户名相同情况

 3.3 有一个输入为空的情况

3.4 两次输入的密码不同 

4.考虑的问题,图像为空

我们允许图像为空,故需要考虑将本地的文件转为MultipartFile。

数据库存入默认头像

根据文件路径获取 MultipartFile 文件_multipartfile他通过路径获取-CSDN博客

4.1 Controller更改

 

package com.example.demo.controller;

import com.example.demo.config.Method;
import com.example.demo.config.Result;
import com.example.demo.constant.Constant;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @RequestMapping("/register")
    public Result registerUser(@RequestParam(required = false) MultipartFile file, String username, String password, String ensurePassword) {
        //当旧密码与新密码所输入的一样,且都不为空才会进行后续操作
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password) || !StringUtils.hasLength(ensurePassword)) {
            return Result.fail(Constant.RESULT_CODE_MESSAGENULL, "你所输入的信息为空,违规");
        }
        //两个密码必须一致才可以进行后续操作
        if (!password.equals(ensurePassword)) {
            return Result.fail(Constant.RESULT_CODE_NOTSAMEPASSWORD, "两次密码输入不一致,违规");
        }
        //需要查询是否存在相同的username,若否则不能注册,让用户重命名
        if (!userService.selectByUsername(username)) {
            return Result.fail(Constant.RESULT_CODE_SAMEUSERNAME, "用户名不能相同,违规");
        }
        String fileName;
        MultipartFile mfile;
        String path;
        //如果图片为空,则保存默认的图片
        if (file == null) {
            fileName = Constant.PIC;
            path = Constant.SAVE_PATH +fileName;
            mfile = Method.getMulFileByPath(path);
        } else {
            fileName = file.getOriginalFilename();
            path = Constant.SAVE_PATH +fileName;
            mfile=file;
        }
        File dest=new File(path);
        try {
            mfile.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail(Constant.RESULT_CODE_UPLOADPICFAIL,"图片上传失败");
        }

        //同时要将密码进行加密BCrypt
        String newpassword=bCryptPasswordEncoder.encode(password);

        //将所输入的数据存入数据库中
        if(userService.insertUserInfo(username,newpassword,fileName,path)){
            return Result.success(true);
        }
        return Result.fail(Constant.RESULT_CODE_FAIL,"上传数据库失败");
    }
}

4.2 Method类

 

package com.example.demo.config;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Method {
    public static MultipartFile getMulFileByPath(String picPath) {
        FileItem fileItem = createFileItem(picPath);
        MultipartFile mfile = new CommonsMultipartFile(fileItem);
        return mfile;
    }

    public static FileItem createFileItem(String filePath) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        int num = filePath.lastIndexOf(".");
        String extFile = filePath.substring(num);
        FileItem item = factory.createItem(textFieldName, "text/plain", true,
                "MyFileName" + extFile);
        File newfile = new File(filePath);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try
        {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))
                    != -1)
            {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return item;
    }

}

4.3 前端测试 

5.前后端交互

5.1 register.html

</head>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>用户注册界面</title>
  <link rel="stylesheet" href="css/common.css">
  <link rel="stylesheet" href="css/register.css">
  <link rel="stylesheet" href="css/upload.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav">
        网页聊天
    </div>
    <div class="container">
        <h1>新用户注册</h1>
        <br>
        <form enctype="multipart/form-data" id="file_upload" class="headForm" onsubmit="return false" action="##"> 
            <div id="test-image-preview" class="iconfont icon-bianjitouxiang">
                <input type="file" name="test" id="test-image-file" class="fileHead" accept="image/gif, image/jpeg, image/png, image/jpg" multiple="multiple">
            </div>
            <div class="headMain">
                <span class="file">上传头像</span>
                <p id="test-file-info" class="fileName"></p>
            </div>
            <br>       
            <div>
            <span class="p">*</span>
            <label for="username">用户名</label>
            <input type="text" name="" id="username" placeholder="" class="register"><br><br>
            
            <span class="q">*</span>
            <label for="pwd">登录密码</label>
            <input type="password" name="" id="pwd" class="register"><br><br>
            <span class="q">*</span>
            <label for="c_pwd">确认密码</label>
            <input type="password" name="" id="c_pwd" class="register"><br><br>
            <input type="checkbox" class="checkbox" name="">
            <span style="font-size:15px">我已阅读并同意《用户注册协议》</span>
            <br><br>
            <input type="submit" name="" value="同意以上协议并注册" class="submit" onclick="register(this)"><br>
            <a href="login.html" class="left">返回首页</a>
            <a href="login.html" class="right">开始登录</a>
            </form>
            </div>
    </div>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript" src="js/register.js"></script>
<script type="text/javascript" src="js/upload.js"></script>
<script>
    
</script>
</body>
</html>

5.2 register.js

var checkbox=document.getElementsByClassName('checkbox');
function register(btn){
    if(checkbox[0].checked==true){
        submitmessage();
    }else{
        alert("请先阅读并同意《用户注册协议》!")
    }
}


function submitmessage(){
    var formData = new FormData();
    formData.append('file', $('.fileHead')[0].files[0]);
    formData.append('username', $("#username").val());
    formData.append('password', $("#pwd").val());
    formData.append('ensurePassword', $("#c_pwd").val());
    var name11 = formData.get("#username");
    $.ajax({
        type: 'post',
        url: '/user/register',
        processData: false,
        async: false,
        contentType: false,
        cache: false,// 使用同步操作
        timeout: 50000, //超时时间:50秒
        data: formData,
        success: function (result) {    // 返回成功
            // console.log(result);
            console.log(name11);
            if(result!=null&&result.status==200){
                alert("注册账号成功,跳转到登陆页面,开始进行聊天吧!")
                location.href="login.html"
                return;
            }else if(result!=null&&result.status==-10){
                alert("用户名不能相同,违规");
            }else if(result!=null&&result.status==-8){
                alert("两次密码输入不一致,违规");
            }else if(result!=null&&result.status==-6){
                alert("你所输入的信息为空,违规");
            }else{
                alert("注册错误,请联系工作人员")
            }
            
        },
        error: function () {
            alert("接口错误");       // 返回失败
        }
    })
}

5.3 upload.js

var fileInput = document.getElementById('test-image-file'),//文件框,里面存的是文件,fileHead
    info = document.getElementById('test-file-info'),//文件名
    preview = document.getElementById('test-image-preview');//文件框,头像显示界面
    dataBase64 = '',
    preview.style.backgroundImage = 'url(../img/个人头像.png)';    //默认显示的图片

    // 监听change事件:
    fileInput.addEventListener('change', upImg);

// 头像上传逻辑函数
function upImg() {
    preview.style.backgroundImage = '';       // 清除背景图片
    if (!fileInput.value) {     // 检查文件是否选择:(此时文件中什么都没选择)
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        info.innerHTML = '没有选择文件';
    } else {
        $('#test-image-preview').removeClass('icon-bianjitouxiang');
        info.innerHTML = '';//此时上传文件成功
    }

    var file = fileInput.files[0];    // 获取File引用
    var size = file.size;
    if (size >= 100 * 1024 * 1024) {     //判断文件大小
        info.innerHTML = '文件大于100兆不行!';
        preview.style.backgroundImage = '';
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        return false;
    }

    if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {    // 获取File信息:
        info.innerHTML = '不是有效的图片文件!';
        preview.style.backgroundImage = '';
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        return;
    }

    // 读取文件:
    var reader = new FileReader();
    reader.onload = function (e) {
        dataBase64 = e.target.result;     // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...}'        
        preview.style.backgroundImage = 'url(' + dataBase64 + ') ';
        preview.style.backgroundRepeat = 'no-repeat';
        preview.style.backgroundSize = ' 100% 100%';
    };
    // 以DataURL的形式读取文件:
    reader.readAsDataURL(file);
    // console.log(file);
}

5.4 upload.css

.reHead{
    margin: 15px 4%; 
}
.headForm{
    text-align: center;
    padding: 40px 0 70px 0;
}
#test-image-preview {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: #F5F5F5;
    color: #fff;
    font-size: 60px;
    text-align: center;
    line-height: 100px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center center;
    margin-bottom: 26px;
}
.fileHead{
    position: absolute;
    width: 100px;
    height: 100px;
    right: 0;
    top: 0;
    opacity: 0;
}
.content-format {
    font-size: 12px;
    font-weight: 400;
    color: rgba(153, 153, 153, 1);
}
.headMain{
    height: 40px;
}
.file {
    position: relative;
    background: #fff;
    color: #F39800;
    font-weight:800;
}
.file input {
    position: absolute;
    font-size: 12px;
    right: 0;
    top: 0;
    opacity: 0;
}
.fileName {
    line-height: 28px;
    font-size: 12px;
    font-weight: 400;
    color: rgba(51, 51, 51, 1);
}
.but{
    text-align: center;
}
.orangeHead{
    width: 40%;
    height: 40px;
    background: #f60;
    border: none;
}
.orangeHead a{
    color: #fff;
}

5.5 register.css

body{
  background: url("../img/coolgirl.jpg");
  background-size:100% 100%;
  background-attachment: fixed;
}
  .container{
    position: absolute;
             top: 50%;
             left: 50%;
             transform: translate(-50%,-50%);
  }
  img{
		width: 4rem;
		height: 4rem;
		margin-left: 50%;
		transform: translateX(-50%);
		margin-top: 0.853rem;
		border-radius: 50%;
	}
	#js_logo_img{
		width: 4rem;
		height: 4rem;
		position: absolute;
		left: 50%;
		transform: translateX(-50%);
		top: 30%;
		opacity: 0;
	}
  h2{
		color: #000066;
		font-size: 0.853rem;
		text-align: center;
		margin: 0;
	}
  form{
    width: 450px;
    margin: 0 auto;
    background: #FFF;
    border-radius: 15px;
    position: relative;
  }
  h1{
    font-size: 28px;
    text-align: center;
    color: #FFF;
  }
  .p{
    color: red;
    margin-left: 33px;
    display: inline-block;
    /* 不占单独一行的块级元素 */
  }
  label{
    font-size: 18px;
    font-weight: bold;
  }
  .register{
    height: 35px;
    width: 300px;
  }
  .q{
    color:red;
    margin-left:17px;
    display:inline-block;
  }
  .checkbox{
    margin-left: 100px;
    display: inline-block;
    width: 15px;
    height: 15px;
  }
  .submit{
    border-radius: 7px;
    margin-left: 150px;
    height: 35px;
    width: 150px;
    background-color: #000;
    border: none;
    display: block;
    padding: 0;
    color: #FFF;
    font-weight: bold;
    cursor: pointer;
  }
  a{
    text-decoration: none;
    font-weight: bold;
  }
  .left,.right{
    position: absolute;
    bottom: 20px;
  }
  .left{
    left: 20px;
  }
  .right{
    right: 20px;
  }

5.6 common.css

/* 放置页面的公共样式 */

/* 去除浏览器默认样式 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 设定页面高度 */
html, body {
    height: 100%;
}

/* 设定导航栏的样式 */
.nav {
    height: 50px;
    background-color: black;
    color: rgb(255, 255, 255);

    /* 使用弹性布局, 让导航栏内部的元素, 垂直方向居中 */
    display: flex;
    align-items: center;
    /* 让里面的元素距离左侧边框, 有点间隙 */
    padding-left: 20px;
}

5.7 测试

注册成功!!!

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值