Spring Security从数据库查询用户信息-密码加密

本文介绍了如何在SpringSecurity框架下实现用户信息查询和密码加密,包括创建UserDetailsService实现类、UserInfo实体、配置认证管理器,以及使用BCryptPasswordEncoder进行密码加密和验证的过程。
摘要由CSDN通过智能技术生成

目录

 一、前提条件

二、核心代码

2.1 UserService

2.2 UserInfo实体类

2.3  修改配置类 配置认证管理器

三、对密码进行加密

 3.1 测试类

 3.2 实现步骤:


 一、前提条件

如果我们要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个实现UserDetailsService接口的实现类,并按照框架的要求进行配置即可。框架会自动调 用实现类中的方法并自动进行密码校验。

二、核心代码

2.1 UserService

@Component
public class UserService implements UserDetailsService {
    //模拟向数据库中插入数据
    static Map<String, UserInfo> map = new HashMap<>();

    static{
        UserInfo u1 = new UserInfo("admin","admin");
        UserInfo u2 = new UserInfo("Sunny","123");
        map.put(u1.getUsername(),u1);
        map.put(u2.getUsername(),u2);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username:"+username);
        //模拟从数据库中查询用户
        UserInfo userInfo = map.get(username);
        if(userInfo==null){
            return null;
        }
        //模拟查询数据库中用户的密码 "{noop}"表示密码没有加密
        String password = "{noop}"+userInfo.getPassword();
        List<GrantedAuthority> list = new ArrayList<>();
        //授权,后期需要改为查询数据库动态获得用户拥有的权限和角色
        list.add(new SimpleGrantedAuthority("add"));
        list.add(new SimpleGrantedAuthority("delete"));
        list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
// 这个User不是我们自定义的User,注意导包不要导错
//import org.springframework.security.core.userdetails.User;
        User user = new User(username, password, list);
        return user;
    }
}

2.2 UserInfo实体类

public class UserInfo {
    String username;
    String password;

    public UserInfo(String username,String password){
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

2.3  修改配置类 配置认证管理器

 

三、对密码进行加密

前面我们使用的密码都是明文的,这是非常不安全的。一般情况下用户的密码需要进行 加密后再保存到数据库中。

常见的密码加密方式有:

3DES、AES、DES:使用对称加密算法,可以通过解密来还原出原始密码 MD5、SHA1:使用单向HASH算法,无法通过计算还原出原始密码,但是可以建立彩虹表进行查表破解

bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题

加密后的格式一般为:

加密后字符串的长度为固定的60位。其中:$是分割符,无意义;2a是bcrypt加密版本号;10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

 

 3.1 测试类

 public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            String password="123456";
            /**
             * BCryptPasswordEncoder是Spring Security
             * 提供的一个加密的API
             */
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String hashPassWord = bCryptPasswordEncoder.encode(password);
            System.out.println(hashPassWord);
            boolean flag = bCryptPasswordEncoder.matches("123456", hashPassWord);
            System.out.println(flag);

        }

可以看到,每次输出的hashPass 都不一样,但是最终的flag都为 true,即匹配成功。

BCryptPasswordEncoder 编码同一个密码后结果都不一样,怎么进行匹配?

  1. 加密(encode):注册用户时,BCrypt.hashpw(密码, 随机盐)得到密码的hash值,然后将其存入数据库中。
  2. 密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密,而是根据数据库查询出来的“密码”拿到密码盐,同一个密码盐+原密码计算 Hash 结果值是能匹配的。

 3.2 实现步骤:

(1):配置类中指定密码加密对象

 (2)第二步:修改UserService实现类

此时 便加密完成了。

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天的接口写完了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值