【密码加密原则三】

目录

1 密码加密原则(续)

1.1 盐值的优化

1.2  Mybatis中的占位符


1 密码加密原则(续)


1.1 盐值的优化

为了进一步保障密码安全,可以考虑使用随机的盐值,但是,需要注意,随机的盐值必须保存下来,否则,当“注册”时使用随机盐进行编码得到密文,后续“登录”时在无法得到相同盐值的情况下,无法编码得到相同的密文,会导致注册的账号无法经过密码验证来登录!

示例:


@Test
void encode() {
    String salt = UUID.randomUUID().toString()
            .replace("-", ""); // 盐值
    String rawPassword = "123456";
    String encodedPassword = DigestUtils.md5DigestAsHex(
            (rawPassword + salt).getBytes());
    System.out.println("盐值:" + salt);
    System.out.println("原文:" + rawPassword);
    System.out.println("密文:" + (salt + encodedPassword));
    // 5571de817ae548439e21b25c51dc355d8dcf37525ca32a3916b56b7db1f15051
    // 1451c0a6320d4aacbd2453862a354e7c7cd8c5ad0d09027f0fc64f0ce52cf2df
}

@Test
void matches() {
    String rawPassword = "123456";
    String dbPassword = "1451c0a6320d4aacbd2453862a354e7c7cd8c5ad0d09027f0fc64f0ce52cf2df";

    String salt = dbPassword.substring(0, 32);
    String encodedPassword = DigestUtils.md5DigestAsHex(
            (rawPassword + salt).getBytes());
    System.out.println("盐值:" + salt);
    System.out.println("原文:" + rawPassword);
    System.out.println("密文:" + (salt + encodedPassword));
    System.out.println("验证结果:" + dbPassword.equals(salt + encodedPassword));
}
 

但是,以上做法仍无法抵御“穷举式的暴力破解”,在这种破解手段面前,是完全无视加密时使用的算法的,而是直接通过你设计算法,一个个的去尝试,直至“试”正确的原始密码。

针对暴力破解,最有效的手段就是:验证码、对恶意访问的客户端实施禁止访问的机制(例如封IP等、封账号)。

另外,还可以使用一些更加安全的算法,来避免被暴力破解!有些用于处理密码加密的算法被刻意的设计成“非常慢”的算法!例如`BCrypt`算法就是非常慢的(个人电脑,每秒13次左右):


BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

@Test
void encode() {
    String rawPassword = "123456";
    System.out.println("原文:" + rawPassword);

    String encodedPassword = passwordEncoder.encode(rawPassword);
    System.out.println("密文:" + encodedPassword);

    // 密文:$2a$10$Ns6YHxeVxdG1aFLkSX/0e.xT9QMKte/wZBIv.fZ/mhNxP7K8RvzPC
    // 密文:$2a$10$TpWV/CzbsTP/nYvmjH3BjuXBjnZUHJ6dkWO8/0CORsXFzIQUojw9K
    // 密文:$2a$10$7LIZM.IxoUy9e1NSkqHEF.7SkeRbvNlNtnlRqY6rUssVNa1T36KAm
    // 密文:$2a$10$6c7EETFK/iRlt3iAxBhsZu/OTFrSo8RZWzGPRJVuCHGek2ms4M71S
    // 密文:$2a$10$LOXtGYZF.MYlrbcDlJ/Q4Okj6VXOV9V3dHNtaAxEbXcZzG2K1Dha2
    // 密文:$2a$10$p8gHsRqNUXUE1l4JFHH.4uDkpu7WArXpPiU4Dxhf2tv.o3BK7PBem
    // 密文:$2a$10$VHAAkbg4cbTfzvP6WiMH8eo95f2j3VKlDtD4t.SmtOjucOIDsuZj2
    // 密文:$2a$10$Pnsmkc8jV.6sILuO4hfb9ui7rpHx2Qk/cj5YBr1YIr.jiRCuKpJ2i
    // 密文:$2a$10$l56hXamC5cGxBsYBcOHfg.g1XbVM21YfWq.4oWm2PUypTfgRrv3O.
    // 密文:$2a$10$iyyAWxSQnG8DNd8qbMon0.gCxy5c7uzxBP3tZOFPIcFg5LxcunIEC
}

@Test
void matches() {
    String rawPassword = "123456";
    System.out.println("原文:" + rawPassword);

    String encodedPassword = "$2a$10$7LIZM.IxoUy9e1NSkqHEF.7SkeRbvNlNtnlRqY6rUssVNa1T36KAm";
    System.out.println("密文:" + encodedPassword);

    System.out.println("验证结果:" + passwordEncoder.matches(rawPassword, encodedPassword));
}
 

提示:`BCrypt`算法本身也是使用了随机的盐值,且盐值是密码的一部分,所以,并不影响其验证密码。

基于`BCrypt`算法的特性(随机盐、非常慢),是目前主流的用于对密码进行加密并用于存储的算法!

提示:`BCrypt`算法本身已经非常安全,通常并不需要使用额外的处理机制,当然,如果你还不放心,也可以继续加盐,或混合其它算法再次处理!通常,没有这个必要性!

1.2  Mybatis中的占位符

在使用Mybatis框架实现数据库编程时,在SQL语句的参数可以使用`#{}`的占位符来表示,例如:

```sql
DELETE FROM pms_album WHERE id=#{id}
```

其实,在`#{}`的大括号中的名称是可以完全随意填写的!例如写成`#{id}`,或`#{abcdefg}`,或`#{0}`等等,都是可以正确执行的!

之所以`#{}`中的名称可以随意填写,是因为以上SQL语句只有1个参数,Mybatis会自动的找到这个参数值用于执行SQL语句,无论名称是什么,都不会影响Mybatis找到这个参数值!

在**非Spring Boot项目**中,如果抽象方法的参数不只1个,默认情况下,Mybatis无法识别任何参数的名称,例如配置为:

```java
int updateNameById(Long id, String name);
```

```xml

    update
        pms_album
    set
        name=#{name}
    where
        id=#{id}

```

执行时将出现错误,如下所示:

Caused by: org.apache.ibatis.binding.BindingException: Parameter 'name' not found. Available parameters are [arg1, arg0, param1, param2]

之所以出现这个错误,是因为所有`.java`文件在执行之前都需要被编译为`.class`文件,最终执行的是`.class`文件,而默认的编译行为会**丢弃所有局部的量(包含局部变量、方法的参数)的名称**!也就是说,以上代码在编译到`.class`文件中后,根本没有`id`、`name`这样的参数名称!

根据以上提示`Available parameters are [arg1, arg0, param1, param2]`,此时,只能使用`arg0`表示第1个参数,使用`arg1`表示第2个参数,或者,使用`param1`表示第1个参数,使用`param2`表示第2个参数……即`arg`开头是使用`0`开始顺序编号的,`param`开头是使用`1`开始顺序编号的,如果你的抽象方法有更多参数,也可以继续编号下去(无视以上信息中是否提示了)。

例如配置为:

```xml

    update
        pms_album
    set
        name=#{arg1}
    where
        id=#{arg0}

```

在Spring Boot中,干预了编译过程,保留了参数名称,所以,在配置SQL语句时,可以在`#{}`中写参数的名称,例如:

```xml

    update
        pms_album
    set
        name=#{name}
    where
        id=#{id}

```

个人主页:居然天上楼

感谢你这么可爱帅气还这么热爱学习~~

人生海海,山山而川

你的点赞 收藏⭐ 留言 加关注✅

是对我最大的支持与鞭策

你可能感兴趣的:(密码加密,java,开发语言)