加盐算法:手撕+Spring Security、提高密码安全性的必杀技

news2024/9/21 0:29:31

目录

一、概念和理解

(一)MD5加密

(二)加密解密过程

(三)加盐

1.什么是盐值?

2.如何加盐?

 二、手写加盐算法

(一)密码工具类

(二)项目改动

 注册

 登录

三、Spring Security 加盐和实现的实现步骤

(一)引入依赖

(二)排除 Spring Security 的自动注入

(三)实现加盐

密码组成

实现加盐

验证密码


一、概念和理解

(一)MD5加密

  • MD5消息摘要算法,属Hash算法一类。
  • MD5算法对输入任意长度的消息进行运行,产生一个128位的消息摘要(32位的数字字母混合码)。
  • 特征:一对一、不可逆。

(二)加密解密过程

(三)加盐

1.什么是盐值?

  • 盐值是指在密码哈希过程中,为了增强密码强度而添加的随机字符串。
  • 通过将一个原始的密码与盐值结合起来进行哈希,以生成一个不可逆的密文,从而增加破解密码的困难度。
  • 盐值通常被保存在数据库中,以便在验证用户的输入密码时使用。

2.如何加盐?

 二、手写加盐算法

(一)密码工具类

package com.example.demo.common;

import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.UUID;

/**
 * 关于密码的一个工具类
 * 主要方法:
 * 1.encrypt 给定明文 得到 数据库密码(创建账号存到数据库使用)
 * 2.encrypt 给定明文和盐值 得到 数据库密码(校验密码使用)
 * 3.verifyPassword 给定明文,校验是否正确
 */
public class PasswordUtils {

    /**
     * 加盐 并生成密码 --- 产生随机盐值进行加密
     *
     * @param password 用户输入的密码
     * @return 数据库密码
     */
    public static String encrypt(String password) {
        if (!StringUtils.hasLength(password)) {
            return null;
        }
        //1 产生 盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        //2 生成加盐 后的密码
        String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //3 数据库密码
        return salt + "&" + saltPassword;
    }

    /**
     * 给定盐值和密码,生成数据库
     *
     * @param password 用户输入的密码
     * @param salt     盐值
     * @return 数据库密码
     */
    private static String encrypt(String password, String salt) {
        if (!StringUtils.hasLength(password) || !StringUtils.hasLength(salt) || salt.length() != 32) {
            return null;
        }
        //1 加密密码
        String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //2 数据库密码
        return salt + "&" + saltPassword;
    }

    /**
     * 校验密码
     *
     * @param inputPassword 用户输入的密码
     * @param finalPassword 数据库密码
     * @return 校验成功、校验失败
     */
    public static boolean verifyPassword(String inputPassword, String finalPassword) {
        if (!StringUtils.hasLength(inputPassword) || !StringUtils.hasLength(finalPassword) || finalPassword.length() != 65) {
            return false;
        }
        String salt = finalPassword.substring(0, 32);
        String finalPassword1 = encrypt(inputPassword, salt);
        return finalPassword.equals(finalPassword1);
    }

}

(二)项目改动

 注册

@RequestMapping("/reg")
    public AjaxResult reg(User user) {
        //1.非空校验 和 参数有效性校验
        if (user == null || !StringUtils.hasLength(user.getUsername()) || !StringUtils.hasLength(user.getPassword())) {
            return AjaxResult.fail(400, "前端数据发送错误!");
        }
        //2.密码加盐处理
        user.setPassword(PasswordUtils.encrypt(user.getPassword()));
        return AjaxResult.success(200, "注册", userService.reg(user));
    }

 登录

@RequestMapping("/login")
    public AjaxResult login(HttpServletRequest request, String username, String password) {
        //1.非空校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return AjaxResult.fail(400, "非法请求: 用户名或密码not Has Length");
        }
        //2.数据库查询
        User user = userService.getUserByName(username);
        if (user != null && user.getId() > 0) {
            //但到这里说明存在这个用户,是还没判断密码是否ok
            if (PasswordUtils.verifyPassword(password,user.getPassword())) {
                //登陆成功:账号密码均正确
                user.setPassword(null);//抹除敏感信息:返回前端数据之前抹除密码这个敏感信息
                //3.将用户信息存储到 session
                HttpSession session = request.getSession(true);
                session.setAttribute(AppVariable.USER_SESSION_KEY, user);
                return AjaxResult.success(200, "登陆成功", user);
            }
        }
        return AjaxResult.success(400, "账号或密码不正确!", null);
    }

三、Spring Security 加盐和实现的实现步骤

  • Spring security是springboot官方提供的一种更加齐全的安全框架。(security -- 安全)
  • Spring Security 的三大功能:授权、认证、安全相关的所有周边产品(比如加盐),其中 加密功能的思路 和我们手写的基本一致。

(一)引入依赖

可以使用Edit Starters插件,在pom.xml中直接按 alt + insert 即可,选择 spring security。或者使用下方的依赖复制粘贴进去也可。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

(二)排除 Spring Security 的自动注入

在启动类中DemoApplication中关闭自动注入

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

(三)实现加盐

密码组成

实现加盐

    /**
     * 加密
     * @param password 用户输入的 明文
     */
    String AddSalt(String password) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String finalPassword = passwordEncoder.encode(password);//数据库密码
        System.out.println(finalPassword);
        return finalPassword;
    }

验证密码

/**
 * 验证密码
 * @param password 用户输入的 明文
 * @param finalPassword 数据库密码
 */
boolean Verify(String password,String finalPassword){
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    return passwordEncoder.matches(password,finalPassword);//使用passwordEncoder.matches对比即可
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/594693.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot如何实现自定义Spring Boot启动器

Spring Boot如何实现自定义Spring Boot启动器 在Spring Boot中&#xff0c;启动器&#xff08;Starter&#xff09;是一组依赖项的集合&#xff0c;它们一起提供了某个特定的功能。使用Spring Boot启动器可以让我们更加方便地集成第三方库和框架&#xff0c;并且可以避免版本冲…

2023年京东618预售数据重磅出炉!(大家电篇:预售额550亿)

2023年5月23日至5月31日&#xff0c;京东618预售期正式落幕。今年的预售&#xff0c;不少行业及品牌首战告捷&#xff0c;拿下了不错的成绩。 数据统计时间&#xff1a;5月23日至5月30日 平台&#xff1a;京东 今晚&#xff0c;鲸参谋率先来盘点一下大家电行业在23日至30日预售…

知名大厂的UI组件库有哪些?

以下是 5 款优秀的 UI 设计组件库的推荐&#xff0c;这些组件库都可以免费获取&#xff0c;帮助你解答疑惑&#xff0c;提供设计参考&#xff0c;并提高工作效率 1、MUI&#xff08;Material-UI&#xff09; 包含 60 类别的 UI 设计组件&#xff0c;可在即时设计资源广场一…

开源!AREX接口自动化回归测试的全过程

AREX是一款开源的基于真实请求与数据的自动化回归测试平台&#xff08;项目地址&#xff1a;https://github.com/arextest&#xff09;&#xff0c;利用JavaAgent技术与比对技术&#xff0c;通过流量录制回放能力实现快速有效的回归测试。同时提供了接口测试、接口比对测试等丰…

Sentinel 介绍及整合OPenFeign及GateWay

Sentinel 介绍 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 Sentinel 具有以下特征: 丰富的应用场景&#xff1a; Sentinel 承接了阿里巴巴近…

IDEA 插件上新! 生成接口文档就是这么快!

当有接口对接需求的时候&#xff0c;开发终于不用再担心 API 文档难写了&#xff0c;也不用再一个个接口文档重新写&#xff01;安装这个 IDEA 插件&#xff0c;可以一步将文档导入到 Postcat。 这款插件操作简单&#xff0c;容易上手&#xff0c;能够让开发者省去API文档编写的…

STM32G0x0系列-软件定时器解决HAL_Delay问题

目录 HAL_Delay函数源码 软件定时器 创建工程试验 1.将对应文件移动到项目位置 2.添加现有文件放到工程中 3.重定向printf 3.验证自己的软件定时器 4.查看现象 HAL_Delay函数使用了中断机制来实现延时功能&#xff0c;当在中断函数中调用HAL_Delay函数需要考虑中断优先…

《操作系统》by李治军 | 实验5.pre - copy_process 代码详解

目录 【前言】 代码分析 1. 申请子进程 PCB 空间 2. 找到子进程的内核栈 3. 父子进程共用同一内存、堆栈和数据代码块 4. 相关寄存器入栈 5. switch_to 返回位置 6. 响应 switch_to 的弹栈工作 7. 更新子进程 PCB 8. 子进程切换流程 【前言】 在李治军老师的《操作系…

MyBatis——缓存

是一种临时存储少量数据至内存或者是磁盘的一种技术.减少数据的加载次数,可以降低工作量,提高程序响应速度 缓存的重要性是不言而喻的。mybatis的缓存将相同查询条件的SQL语句执行一遍后所得到的结果存在内存或者某种缓存介质当中&#xff0c;当下次遇到一模一样的查询SQL时候…

Yolov8涨点神器:ODConv+ConvNeXt提升小目标检测能力

1.涨点神器结合,助力YOLO 1.1 ICLR 2022涨点神器——即插即用的动态卷积ODConv 论文:Omni-Dimensional Dynamic Convolution 论文地址:Omni-Dimensional Dynamic Convolution | OpenReview ODConv通过并行策略引入一种多维注意力机制以对卷积核空间的四个维度学习更灵活的…

项目所需的Python版本+国内源+虚拟环境+用Conda创建环境

文章目录 &#xff08;一&#xff09;Python&#xff08;1.1&#xff09;国内源&#xff08;1.2&#xff09;设置源&#xff08;全局&#xff09;&#xff08;1.3&#xff09;使用源&#xff08;单次&#xff09; &#xff08;二&#xff09;Python环境&#xff08;2.1&#xf…

【数据结构与算法】力扣:栈和队列(一)

1 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开…

vue diff算法与虚拟dom知识整理(13) 手写patch子节点更新换位策略

上一文中我们编写了 patch中新旧节点都有子节点的 插入节点的逻辑 但旧节点的子节点发生顺序 或数量变化 我们还没有处理 那我们现在继续 我们先来看看 原本是怎么写的 我们打开我们的案例 找到 node_modules 下面的snabbdom/src下面的 init.ts文件 我们在里面找到一个 updat…

Openai+Deeplearning.AI: ChatGPT Prompt Engineering(六)

想和大家分享一下最近学习的Deeplearning.AI和openai联合打造ChatGPT Prompt Engineering在线课程.以下是我写的关于该课程的前五篇博客&#xff1a; ChatGPT Prompt Engineering(一)ChatGPT Prompt Engineering(二)ChatGPT Prompt Engineering(三)ChatGPT Prompt Engineering…

QML Text 元素

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在 QML 中,Text 和 Label 是两种常用的元素(Label 继承于 Text),用于显示文本内容。虽然它们看起来很相似,但在使用和功能上有一些不同。 对于 Text 元素,比较重要的是 text 与 font 属性,一旦指定了…

Linux常见IO模型-3

在前两篇博客中&#xff0c;我们讲述了常见的IO模型&#xff0c;并对多路转接模型中的select模型进行了细致介绍和具体的代码实现。那么接下来&#xff0c;我们在本篇博客中将对剩余的多路转接模型中的&#xff1a;poll和epoll进行介绍。 目录 1.poll 1.1操作流程 1.2代码实…

硬件系统工程师宝典(27)-----MOSFET、BJT搭配,干活不累

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到场效应管的原理是通过“监测”栅极和源极间电压来实现控制漏极-源极之间电流的目的。今天我们来讲讲场效应管如何和BJT搭配设计控制电路…

【P44】JMeter 模块控制器(Module Controller)

文章目录 一、模块控制器&#xff08;Module Controller&#xff09;参数说明二、测试计划设计 一、模块控制器&#xff08;Module Controller&#xff09;参数说明 提供了一种在运行时将测试计划片段替换为当前测试计划的机制&#xff1b;模块控制器的目标是为增加脚本的复用…

springboot+vue实验室预约设备报修管理系统

本实验室管理系统管理员功能有个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;公告信息管理&#xff0c;知识库管理&#xff0c;实验课程管理&#xff0c;实验室信息管理&#xff0c;实验室预约管理&#xff0c;实验设备管理&#xff0c;采购记录管理&#xff0…