08 SpringSecurity-密码加密

文章配套代码:https://gitee.com/lookoutthebush/spring-security-demo

一、SpringSecurity加密机制

Spring Security内置了密码加密机制,只需使用一个PasswordEncoder接口即可

public interface PasswordEncoder {
    String encode(CharSequence rawPassword);

    boolean matches(CharSequence rawPassword, String encodedPassword);

    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

PasswordEncoder接口定义了encode和matches两个方法,当用数据库存储用户密码时,加密过程用 encode方法,matches方法用于判断用户登录时输入的密码是否正确。

此外,SpringSecurity还内置了几种常用的PasswordEncoder接口实现类,例如,StandardPasswordEncoder中的常规摘要算法(SHA-256等)、BCryptPasswordEncoder加密,以及类似 BCrypt的慢散列加密Pbkdf2PasswordEncoder等,官方推荐使用BCryptPasswordEncoder。

我们这里使用官方推荐的BCryptPasswordEncoder。

二、注入BCryptPasswordEncoder

/**
 * @author LookOutTheBush
 */
@Configuration
public class PasswordEncoderConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    }
}

三、创建用户时加密

@Service
public class UserServiceImpl implements UserDetailsService {
    @Resource
    private UserDao userDao;
    @Resource
    private PasswordEncoder passwordEncoder;

    public UsersDO createUser(UsersDO usersDO){
        //参数校验 todo
        usersDO.setPassword(passwordEncoder.encode(usersDO.getPassword()));
        usersDO.setEnable(true);
        return userDao.createUser(usersDO);
    }
}

四、登录时密码校验

这部分SpringSecurity会使用我们暴露的加密方式来校验密码,不需要我们操作。

五、测试

1.直接生成加密后的密码。

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(12);
        String encode = bCryptPasswordEncoder.encode("123");
        System.out.println(encode);
    }

2.然后手动添加到数据库中 

3.启动项目测试:

 输入账号密码,登录成功。

### 在 Spring Security 中集成 SM2 加密 为了在 Spring Security 中实现用户密码的 SM2 国密加密,可以自定义 `PasswordEncoder` 接口来处理基于 SM2 的加密逻辑。具体来说,通过创建一个新的类继承 `PasswordEncoder` 并重写其方法以支持 SM2 算法。 #### 自定义 PasswordEncoder 类 下面展示了一个简单的例子,说明如何构建一个能够利用 SM2 对密码进行编码和匹配验证的组件: ```java import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.security.crypto.password.PasswordEncoder; public class Sm2PasswordEncoder implements PasswordEncoder { static { // 注册 Bouncy Castle 提供者以便使用国密算法 if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null){ Security.addProvider(new BouncyCastleProvider()); } } @Override public String encode(CharSequence rawPassword) { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("SM2", "BC"); ECGenParameterSpec sm2Params = new ECGenParameterSpec("sm2p256v1"); SecureRandom random = new SecureRandom(); keyGen.initialize(sm2Params, random); KeyPair pair = generateKey(); // 获取公私钥对[^1] byte[] encryptedBytes = encrypt(rawPassword.toString().getBytes(), pair.getPublic()); return Base64.getEncoder().encodeToString(encryptedBytes); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } private byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception{ Cipher cipher = Cipher.getInstance("SM2", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { try { byte[] decryptedBytes = decrypt(Base64.getDecoder().decode(encodedPassword)); return Arrays.equals(decryptedBytes, rawPassword.toString().getBytes()); } catch (Exception e) { return false; } } private byte[] decrypt(byte[] data) throws Exception{ PrivateKey privateKey = ... ;// 需要从存储介质读取对应的私钥 Cipher cipher = Cipher.getInstance("SM2", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } } ``` 请注意,在实际应用环境中应当更加谨慎地管理秘钥材料的安全性和生命周期,并考虑性能优化等问题。上述代码片段仅作为概念证明用途。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

七号公园的忧伤

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

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

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

打赏作者

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

抵扣说明:

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

余额充值