电子公文传输系统安全-进展2

- 上周任务完成情况
完成对于登陆过程中的加盐操作:

 SM3加盐算法存储密码的实现类
 加盐思路: 1.通过UUID拿到盐值 2.拼接:盐值+明文密码 3.对2中数据进行SM3哈希 4.拼接: 盐值 + ”^“ + 3中的哈希值
 明文密码走完上述流程后后存入数据库
 登录验证: 1.根据用户名在数据库里得到对应的密文 2.根据密文密码获取该用户的盐值 3.将用户输入的登录密码走完上述加盐思路 4.与数据库密文密码进行对比

相关代码:

 

Sm3SaltUtil.java

 

 

package com.example.demo.util;

import org.springframework.util.StringUtils;

import java.util.UUID;
import org.bouncycastle.crypto.digests.SM3Digest;

public class Sm3SaltUtil {
    /**
     * 用户注册
     * 调用该方法进行SM3加盐处理后存入数据库
     * @param password
     * @return
     */
    public static String encrypt(String password) {
        // 1.生成盐值
        String salt = UUID.randomUUID().toString().replace("-","");

        // 2.生成加盐后的SM3哈希值
        String saltPassword = sm3Hash(salt + password);

        // 3.生成最终存入数据库的加密密码   65位固定规则
        String finalPassword = salt + "^" + saltPassword;
        return finalPassword;
    }

    /**
     * 用户登录的工具方法
     * 该方法是对用户输入的密码进行上述加盐操作后与数据库密文密码进行比较的工具方法
     * @param password
     * @param salt
     * @return
     */
    public static String encrypt(String password, String salt) {
        // 1.得到加盐之后的SM3哈希值
        String saltPassword = sm3Hash(salt + password);

        // 2.生成最终密码
        String finalPassword = salt + "^" + saltPassword;

        return finalPassword;
    }

    /**
     * 用户登录密码正确性验证
     * @param password           用户登录时输入的密码
     * @param dbFinalPassword    用户数据库里最终的加密密码
     * @return
     */
    public static boolean check(String password, String dbFinalPassword) {
        if (StringUtils.hasLength(password)
                && StringUtils.hasLength(dbFinalPassword)
                && dbFinalPassword.length() == 97) {
            String salt = dbFinalPassword.split("\\^")[0];
            String confirmFinalPassword = encrypt(password, salt);

            if (dbFinalPassword.equals(confirmFinalPassword)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 使用SM3算法进行哈希计算
     * @param input 输入字符串
     * @return 哈希结果的十六进制表示
     */
    private static String sm3Hash(String input) {
        SM3Digest digest = new SM3Digest();
        byte[] data = input.getBytes();
        digest.update(data, 0, data.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return bytesToHex(hash);
    }

    /**
     * 将字节数组转换为十六进制字符串表示
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }
}

 

login:

package com.example.demo.controller;

import com.example.demo.component.GeneratorId;
import com.example.demo.component.TokenUtil;
import com.example.demo.enums.Code;
import com.example.demo.enums.Keys;
import com.example.demo.pojo.entity.UserInfo;
import com.example.demo.service.UserInfoService;
import com.example.demo.util.Sm3SaltUtil;
import com.example.demo.util.Return;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
@ResponseBody
@RequestMapping("/public/user")
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private GeneratorId generatorId;

    @GetMapping("/login")
    public Return userLogin(UserInfo user, HttpServletRequest request) {
        if (user == null
                || !StringUtils.hasLength(user.getAccount())
                || !StringUtils.hasLength(user.getPassword())) {
            // 非法参数
            return Return.fail(Code.FAIL_NORMAL);
        }

        // 处理登录请求:查询数据库密码通过Sm3封装的方法进行对比
        // 1.查询数据库
        UserInfo dbUser = userInfoService.login(user);
        if (dbUser == null || dbUser.getId() <= 0) {
            return Return.fail(Code.FAIL_LOGIN);
        }

        // 2.调用Sm3工具类方法进行对比
        if (!Sm3SaltUtil.check(user.getPassword(),dbUser.getPassword())) {
            // 密码不一样,登录失败
            return Return.fail(Code.FAIL_LOGIN);
        }

        // 3.登录成功,可存入redis key-token:生成的随机唯一值  value:user
        String ip = request.getRemoteAddr();
        dbUser.setPassword("******");
        dbUser.setIp(ip);
        //TokenUtil.setObjectInSession(ApplicationVariable.USER_SESSION_KRY,dbUser,request);

        // 3.redis实现token
        // 3.1 生成随机token
        String token = UUID.randomUUID().toString().replace("-","");
        // 3.2 保存到redis
        tokenUtil.setUserInfo(token,dbUser,30L, TimeUnit.MINUTES);

        // 5.返回登录成功 返回token  后续携带token
        return Return.success(Code.SUCCESS_NORMAL,token);
    }

    @PostMapping("/enroll")
    public Return enroll(UserInfo user, HttpServletRequest request) {
        // 非法校验
        if (user == null
                || !StringUtils.hasLength(user.getAccount())
                || !StringUtils.hasLength(user.getPassword())) {
            return Return.fail(Code.FAIL_NORMAL);
        }

        // 调用Sm3工具类进行密码加密
        String password = user.getPassword();
        password = Sm3SaltUtil.encrypt(password);
        user.setPassword(password);

        // 获取ip
        String ip = request.getRemoteAddr();
        user.setIp(ip);

        // 生成id
        user.setId(generatorId.nextId(Keys.USER_ID.getKey()));

        // 注册
        int result = userInfoService.enroll(user);
        if (result != 1) {
            // 注册失败
            return Return.fail(Code.FAIL_NORMAL);
        }

        // 返回
        return Return.success(Code.SUCCESS_NORMAL);
    }

    @GetMapping("/logout")
    public Return logout(@RequestHeader("token")String token) {
        // 删除token
        tokenUtil.removeUserInfo(Keys.USER_TOKEN + token);
        return Return.success(Code.SUCCESS_NORMAL);
    }

    @RequestMapping("/list")
    public Return list(@RequestHeader("token") String token) {
        // 1. 查看权限
        UserInfo user = tokenUtil.getUserInfo(token);
        if (user == null || user.getId() == 1) {
            return Return.fail(Code.NOT_SEE);
        }
        // 2. 返回
        return Return.success(Code.SUCCESS_NORMAL, userInfoService.list());
    }

    @RequestMapping("/count")
    public Return count() {
        return Return.success(Code.SUCCESS_NORMAL,userInfoService.count());
    }

    @GetMapping("/info")
    public Return info(@RequestHeader("token")String token) {
        if (token == null) {
            return Return.fail(Code.FAIL_NORMAL);
        }

        UserInfo userInfo = tokenUtil.getUserInfo(token);
        if (userInfo == null) {
            return Return.fail(Code.FAIL_NORMAL);
        }
        UserInfo userInfoVo = new UserInfo();
        userInfoVo.setAccount(userInfo.getAccount());
        userInfoVo.setStatus(userInfo.getStatus());
        return Return.success(Code.SUCCESS_NORMAL,userInfoVo);
    }
}

  

实验预期:

 

 

- 本周计划

完成审计的相关设计

实验代码:

 

 

 

实验预期:

 

posted @ 2024-05-26 18:46  俊凯今天吃什么  阅读(66)  评论(0)    收藏  举报
Live2D