Java RSA加密工具类(含密钥对生成和根据私钥计算公钥)

news2025/1/21 19:54:28

RSA算法是一种常用的非对称加密算法,它具有以下主要特点:

1.非对称性:RSA 使用一对密钥——公钥和私钥。公钥用于加密,私钥用于解密,也可以反过来使用私钥签名、公钥验证。相对于对称加密的单一密钥,非对称性提高了安全性。

2.安全性高:RSA 的安全性依赖于大整数分解的数学难题。当前计算能力下,分解足够大的整数非常困难,因此 RSA 算法在合理的密钥长度下非常安全(通常建议使用 2048 位或更高的密钥长度)。

3.密钥长度可调:RSA 算法的密钥长度通常为 1024、2048 或 4096 位。密钥长度越长,安全性越高,但计算速度越慢。

4.加密与签名:RSA 不仅可以用于加密,还可以用于数字签名。用私钥签名的消息可以用公钥验证,确保消息的完整性和真实性,特别适合身份认证等场景。

5.加密速度较慢:与对称加密算法(如 AES)相比,RSA 的加密和解密速度较慢,因此它一般用于加密小数据或加密对称密钥(例如在 TLS/SSL 中),然后使用对称加密算法进行数据传输。

6.不可逆性:使用公钥加密的数据只能通过对应的私钥解密,私钥加密(签名)也只能用公钥验证,保障了数据安全传输。

7.抗碰撞性:因为密钥的唯一性和大整数分解的困难,RSA 很难被伪造或碰撞。即使加密内容和公钥被获取,攻击者也很难推导出私钥。

RSA的典型应用场景
1.安全数据传输:如 SSL/TLS 协议中,用于安全地传输加密的对称密钥。
2.身份验证和授权:如数字签名、电子签名中,保障签名的真实性和防篡改性。
3.数字证书:数字证书(如 HTTPS 中的证书)使用 RSA来提供加密和验证身份。


RSA 由于其高安全性和可靠性,广泛用于现代网络安全通信中。

直接上代码

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author Sakura
 * @date 2024/11/11 11:11
 */
public class RSAUtil {

    // 定义密钥长度
    private static final int KEY_SIZE = 2048;
    private static final String ALGORITHM = "RSA";

    /**
     * 生成RSA密钥对
     * @return KeyPair 包含公钥和私钥
     * @throws Exception 如果生成失败
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 使用公钥加密
     * @param data 待加密的数据
     * @param publicKeyStr Base64编码的公钥字符串
     * @return 加密后的数据(Base64编码)
     * @throws Exception 如果加密失败
     */
    public static String encrypt(String data, String publicKeyStr) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(publicKeyStr);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用私钥解密
     * @param encryptedData Base64编码的加密数据
     * @param privateKeyStr Base64编码的私钥字符串
     * @return 解密后的数据
     * @throws Exception 如果解密失败
     */
    public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyStr);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedData = cipher.doFinal(decodedData);
        return new String(decryptedData);
    }

    /**
     * 将Base64编码的公钥字符串转换为PublicKey对象
     * @param publicKeyStr Base64编码的公钥字符串
     * @return PublicKey对象
     * @throws Exception 如果转换失败
     */
    public static PublicKey getPublicKeyFromBase64(String publicKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 将Base64编码的私钥字符串转换为PrivateKey对象
     * @param privateKeyStr Base64编码的私钥字符串
     * @return PrivateKey对象
     * @throws Exception 如果转换失败
     */
    public static PrivateKey getPrivateKeyFromBase64(String privateKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 将PublicKey对象转换为Base64编码的字符串
     * @param publicKey PublicKey对象
     * @return Base64编码的公钥字符串
     */
    public static String encodePublicKeyToBase64(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    /**
     * 将PrivateKey对象转换为Base64编码的字符串
     * @param privateKey PrivateKey对象
     * @return Base64编码的私钥字符串
     */
    public static String encodePrivateKeyToBase64(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    /**
     * 从 RSA 私钥计算出对应的公钥
     * @param privateKey RSA 私钥对象
     * @return PublicKey 对象
     * @throws Exception 如果转换失败
     */
    public static PublicKey getPublicKeyFromPrivateKey(PrivateKey privateKey) throws Exception {
        // 检查私钥类型是否为 RSA 私钥
        if (!(privateKey instanceof RSAPrivateKey)) {
            throw new IllegalArgumentException("The provided key is not an RSA private key.");
        }

        // 从私钥中提取模数和私钥指数
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
        java.math.BigInteger modulus = rsaPrivateKey.getModulus();
        java.math.BigInteger publicExponent = java.math.BigInteger.valueOf(65537); // 常用的公钥指数

        // 使用模数和公钥指数构造公钥规范
        RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

        // 根据规范生成公钥
        return keyFactory.generatePublic(publicKeySpec);
    }

    public static void main(String[] args) throws Exception {
        // 生成私钥和公钥
//        KeyPair keyPair = generateKeyPair();
//        String publicKeyStr = encodePublicKeyToBase64(keyPair.getPublic());
//        String privateKeyStr = encodePrivateKeyToBase64(keyPair.getPrivate());
//        System.out.println(publicKeyStr);
//        System.out.println(privateKeyStr);

        // 公钥对外暴露加密用
        String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuggI4MbASTLHkTbqn6kKIDSKqFKMkiqVymD6DnY5Rcx9U8X97pjK/0pgRvu1xKs4S8Zwo6dgRxjX9Tzao/2OsxjJBIecj6iX47nx7vz6W30G7D+fOu5pNd9iqtu99tcNx+jen5vgqda5NmDHO4sg0oQsNqUy4+jTx+QeU5x0NesvGHO8A+dEKAbDGpyak6MH7X7N9CWTyRyLlmh0jqqc2zs0pkUJsHqtBO7EkPsmI82pSbCIPWmviBN1Z4OXz0bUJdgs2785O+91E00EP0Ktnsvgqg6rKJ2LA7EZczMpcipkCcxjEYMnU+TIIrkXiJX/QrLoOnwJNqUPxfy6haNDcwIDAQAB";
        // 私钥服务器保留解密用
        String privateKeyStr = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6CAjgxsBJMseRNuqfqQogNIqoUoySKpXKYPoOdjlFzH1Txf3umMr/SmBG+7XEqzhLxnCjp2BHGNf1PNqj/Y6zGMkEh5yPqJfjufHu/PpbfQbsP5867mk132Kq27321w3H6N6fm+Cp1rk2YMc7iyDShCw2pTLj6NPH5B5TnHQ16y8Yc7wD50QoBsManJqTowftfs30JZPJHIuWaHSOqpzbOzSmRQmweq0E7sSQ+yYjzalJsIg9aa+IE3Vng5fPRtQl2Czbvzk773UTTQQ/Qq2ey+CqDqsonYsDsRlzMylyKmQJzGMRgydT5MgiuReIlf9Csug6fAk2pQ/F/LqFo0NzAgMBAAECggEAFVt+yW+H+99ckgtf/FyH0RK3KIPxp4ZEFCv2CVsBUEYdzVRZxt67z3tWek/DmoSdvfVWUTOSFheAE6Oc5l7h1yXtThvTmZqddYOPhwR8Kay88rqLKVTdt1WiGkOIF6Kw7laJ2IEo1dbVBK0vsmJSrliGSu/EW+4LAlPqN2cq4FWhtIA5yV3VUuScV9/rI9jvYiwP2ltVUs92Mbkj8AHOpMR+ZrijJupXoWldLSFA91BitKSAZga2xkLRMWeT1TNwhMEU4ihZTJBfFICuGDxzdUXWGXqm8lvMR0bSuerIiXRYspQ/DyobfEfggI+lYeLscp7DtGu0DwMlvrTdNkS2AQKBgQDkwgZ6EGWKVu3Qu3kYLt6gGtqxcUBfbdZyvJFRTxDda5RIFUn3NUDwXNMzB+bZpR4G42P6oVQON8BtMu3tNCUr/97oiTfEMrkkiIRzCVDOrmmrXtmus6rmcDKChlZrfb5TzoHa1borEEFRV7QCoA1ChEkxEMJoL7P39tQ8BqCnMwKBgQDQL2/m2PsIl7wEl5xC+uFrqfd4bl9Ljmt9Ywy0J1DYY/obrtGifPGnkePRAh+o4s7eP2brtBFiRG3/fNOMgHsmk501g3t/wbQ3m0JsKTN6/AtDVcwKTe4ysZpJDVaaJygTzoRRZ/opo77LBc8e7WxZedixM9EFgtFbQCqsqa3ywQKBgEO/Vo2152yF/B5SNzW7Q8Fk0pm0cZ0ReW43fE35PYRlxN9oNqSYx+enhgDZ+TtB1Fez5jsmpi8jwcBVUfNq+wtB1vFFGhfn8b7pE1jCTIU5UCApkgxUN2vRlJPlVxi0f7ZwNTLrExyHzuBZOf2BCwxFAywdy4VxgzoPhqFUUSXTAoGAQelS52Z5C/5mM5oAiiA98EVOqV1gZF6B35/VbNApw2jbzZnqmyQtqh0BYLHobiLo1eqC3ksTWeZKYSIXJBulYdBIbKHlHsyoDxbjz7S3rM9RjY8DW5vSt1ANheVoLsQI50RyFgfyZu6FwGdlbOhEbouqNGgwXCtPtzE4kZPjE8ECgYEA0LY49wpA3UQc8d2PEhTleRhNkpBGbV+wBDrJOlVoxIrTzFsk00vnPGf4OCwIEagxxmdI51dgXgq0BHU/ry3t1fAI1y3YL0WLJxuTQpS0iETcwL/gYkgGLRASm9cswRy+NEKx0l5shMT/0Ow8ntFrdRYOkfGtLIDlXx4LezhsUaY=";
        // 带加密密码
        String password = "123456";

        // 加密后字符串
        String str = encrypt(password, publicKeyStr);
        System.out.println(str);
        // 解密字符串
        String str1 = decrypt(str, privateKeyStr);
        System.out.println(str1);

        // 如果只知道私钥计算公钥
        PublicKey publicKeyFromPrivate = RSAUtil.getPublicKeyFromPrivateKey(getPrivateKeyFromBase64(privateKeyStr));

        // 打印公钥
        System.out.println(Base64.getEncoder().encodeToString(publicKeyFromPrivate.getEncoded()));


    }
}

我们可以通过下面的方法生成密钥对

在这里插入图片描述
在这里插入图片描述

我们用生成的密钥对测试一下,可以看到能正常加解密以及通过私钥计算公钥

在这里插入图片描述
在这里插入图片描述

这里有一点要注意,尽管我们每次都使用同一个公钥进行加密,但是得到的加密字符串是不一样的,这是因为在 RSA 加密中,特别是使用 PKCS#1 v1.5 填充模式(即 RSA/ECB/PKCS1Padding),PKCS#1 v1.5 会在加密前对明文进行特定的随机填充,确保每次加密结果不同。

在这里插入图片描述

下面是 RSA2 的(注意使用了"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"填充,所以需要对接方也需要使用相同的填充方式才可以)

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author Sakura
 * @date 2024/12/6 19:10
 */
public class RSA2Util {

    // 定义密钥长度
    private static final int KEY_SIZE = 1024; // 1024 2048 长度越大越安全但是数据长度越长
    private static final String ALGORITHM = "RSA";

    /**
     * 生成RSA密钥对
     *
     * @return KeyPair 包含公钥和私钥
     * @throws Exception 如果生成失败
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 使用公钥加密
     *
     * @param data         待加密的数据
     * @param publicKeyStr Base64编码的公钥字符串
     * @return 加密后的数据(Base64编码)
     * @throws Exception 如果加密失败
     */
    public static String encrypt(String data, String publicKeyStr) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(publicKeyStr);
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用私钥解密
     *
     * @param encryptedData Base64编码的加密数据
     * @param privateKeyStr Base64编码的私钥字符串
     * @return 解密后的数据
     * @throws Exception 如果解密失败
     */
    public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyStr);
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedData = cipher.doFinal(decodedData);
        return new String(decryptedData);
    }

    /**
     * 使用私钥对数据进行签名(SHA256withRSA)
     *
     * @param data         待签名的数据
     * @param privateKeyStr Base64编码的私钥字符串
     * @return 签名后的数据(Base64编码)
     * @throws Exception 如果签名失败
     */
    public static String sign(String data, String privateKeyStr) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyStr);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signedData = signature.sign();
        return Base64.getEncoder().encodeToString(signedData);
    }

    /**
     * 使用公钥验证签名(SHA256withRSA)
     *
     * @param data         原始数据
     * @param signedData   Base64编码的签名数据
     * @param publicKeyStr Base64编码的公钥字符串
     * @return 验签结果,true为签名有效
     * @throws Exception 如果验证失败
     */
    public static boolean verify(String data, String signedData, String publicKeyStr) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(publicKeyStr);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        byte[] decodedSignedData = Base64.getDecoder().decode(signedData);
        return signature.verify(decodedSignedData);
    }

    public static PublicKey getPublicKeyFromBase64(String publicKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    public static PrivateKey getPrivateKeyFromBase64(String privateKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }

    public static String encodePublicKeyToBase64(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    public static String encodePrivateKeyToBase64(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    public static void main(String[] args) throws Exception {
        // 生成私钥和公钥
        KeyPair keyPair = generateKeyPair();
        String publicKeyStr = encodePublicKeyToBase64(keyPair.getPublic());
        String privateKeyStr = encodePrivateKeyToBase64(keyPair.getPrivate());

        System.out.println("公钥: " + publicKeyStr);
        System.out.println("私钥: " + privateKeyStr);

        // 测试加密解密
        String data = "qaz123456.";
        String encryptedData = encrypt(data, publicKeyStr);
        System.out.println("加密后: " + encryptedData);
        String decryptedData = decrypt(encryptedData, privateKeyStr);
        System.out.println("解密后: " + decryptedData);

        // 测试签名和验签
        String signature = sign(data, privateKeyStr);
        System.out.println("签名: " + signature);
        boolean isVerified = verify(data, signature, publicKeyStr);
        System.out.println("验签结果: " + isVerified);
    }
}

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

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

相关文章

无数据库开源Wiki引擎WikiDocs

简介 什么是 WikiDocs ? WikiDocs 是一个无数据库的开源 Markdown 文件平面 Wiki 引擎。它旨在提供一个简单、灵活且易于使用的 Wiki 解决方案,允许用户创建和管理文档而无需依赖传统数据库。 主要特点 无数据库:使用纯文本文件存储数据&am…

Spring Boot 配置(官网文档解读)

目录 摘要 Spring Boot 配置加载顺序 配置文件加载顺序 Spring Boot 配置加载方式 Value Value 注解简单示例 ConfigurationProperties 启动 ConfigurationProperties ConfigurationProperties 验证 ConfigurationProperties 与 Value 对比 Autowired Autowired 自…

Comment(爆破+git泄漏+二次注入)

通过爆破密码的后三位,获得账号为:zhangwei666 F12查看控制台 使用bugscanteam的githack工具,下载泄漏的源码,根据控制台的提示,完整源码还在历史的commit中 git log –reflog 查看历史记录 查看最新的提交记录&#…

C++otlv4连接sql serveer使用记录(注意点)

C使用otlv4在做插入时,有一些设计的坑需要注意 插入数据: 当要给表中插入单个字符时,数据库表设计使用varchar(1)是合理的,但是otlv4一直报错char。 后续查很久才知道,otlv4所写的绑定的字符数组的长度应该实际数组…

2024又是一年的CSDN之旅-总结过去展望未来

一、前言 一年就这样在忙忙碌碌的工作和生活中一晃而过,总结今年在CSDN上发表的博客,也有上百篇之多,首先感谢CSDN这个平台,能让我有一个地方记录工作中的点点滴滴,也在上面学到了不少知识,解决了工作中遇到…

JDK长期支持版本(LTS)

https://blogs.oracle.com/java/post/the-arrival-of-java-23 jdk长期支持版本(LTS):JDK 8、11、17、21:

大数据学习(37)- Flink运行时架构

&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦&#x1f91…

“AI 大模型内容安全审核软件系统:守护网络世界的卫士

在如今这个信息爆炸的互联网时代,网络上的内容那是五花八门、层出不穷。这时候,咱就得靠 AI 大模型内容安全审核软件系统来给咱把把关了。 咱就说社交媒体平台吧,每天都有海量的用户在上面发布文字、图片、视频啥的。要是没有一个靠谱的审核系…

pyspark连接clickhouse数据库的方式(其它数据库同样适用)

目录 一、背景简记二、pyspark连接clickhouse方式记录三、结语参考学习博文 一、背景简记 实际工作中,大部分所用的数据存储地址都是在数据库中,如我司现在常用的数据库是clickhouse,相关数据的统计分析都在此上操作。如果想用pyspark连接cl…

C 语言雏启:擘画代码乾坤,谛观编程奥宇之初瞰

大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。* 这一课主要是让大家初步了解C语言,了解我们的开发环境,main函数,库…

nacos2.3.0 接入pgsql或其他数据库

首先尝试使用官方插件进行扩展,各种报错后放弃,不如自己修改源码吧。 一、官方解决方案 1、nocos 文档地址:Nacos 配置中心简介, Nacos 是什么 | Nacos 官网 2、官方解答:nacos支持postgresql数据库吗 | Nacos 官网 3、源码下载地…

随遇随记篇

vue 函数 unref() 获取原始值 ref 定义的属性 需要 .value 才能拿到值&#xff0c;unref 直接返回原始值&#xff1b;若属性不是ref 定义的&#xff0c;也是直接返回原始值&#xff1b; /* description: 是否必填*/required?: boolean | Ref<boolean>.....let value …

网站HTTP改成HTTPS

您不仅需要知道如何将HTTP转换为HTTPS&#xff0c;还必须在不妨碍您的网站自成立以来建立的任何搜索排名权限的情况下进行切换。 为什么应该从HTTP转换为HTTPS&#xff1f; 与非安全HTTP于不同&#xff0c;安全域使用SSL&#xff08;安全套接字层&#xff09;服务器上的加密代…

微软Win10 RP 19045.5435(KB5050081)预览版发布!

系统之家1月20日最新报道&#xff0c;微软面向Release Preview频道的Windows Insider项目成员&#xff0c;发布了适用于Windows10 22H2版本的KB5050081更新&#xff0c;更新后系统版本号将升至19045.5435。本次更新增加了对GB18030-2022标准的支持&#xff0c;同时新版日历将为…

从提供的 package.json 文件可以看出,项目已经集成了 vue-cli-service lint --fix,并且配置了相关的工具和脚本

文章目录 1. 确认 vue-cli-service lint 已集成2. 确认 lintOnSave 是否启用示例&#xff1a;vue.config.js 3. 确认 ESLint 配置4. 确认 Git 钩子配置5. 如何实现保存时自动修复&#xff08;1&#xff09;启用 lintOnSave&#xff08;2&#xff09;配置编辑器的 ESLint 插件&a…

2024年博客之星主题创作|Android 开发:前沿技术、跨领域融合与就业技能展望

目录 引言 一、推动 Android 应用创新的核心力量 1.1 人工智能与机器学习的崛起 1.2 增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;的应用扩展 1.3 5G技术的推动 1.4 跨平台开发技术的成熟 1.4.1 React Native 1.4.2 Flutter 1.4.3 Taro …

mac 安装mongodb

本文分享2种mac本地安装mongodb的方法&#xff0c;一种是通过homebrew安装&#xff0c;一种是通过tar包安装 homebrew安装 brew tap mongodb/brew brew upate brew install mongodb-community8.0tar包安装 安装mongodb 1.下载mongodb社区版的tar包 mongdb tar包下载地址 2…

Nvidia Blackwell架构深度剖析:深入了解RTX 50系列GPU的升级

在CES 2025上&#xff0c;英伟达推出了基于Blackwell架构的GeForce RTX 50系列显卡&#xff0c;包括RTX 5090、RTX 5080、RTX 5070 Ti和RTX 5070。一段时间以来&#xff0c;我们已经知晓了该架构的各种细节&#xff0c;其中许多此前还只是传闻。不过&#xff0c;英伟达近日在20…

抽奖系统(4——活动模块)

1. 活动创建 需求回顾 创建的活动信息包含&#xff1a; 活动名称活动描述关联的一批奖品&#xff0c;关联时需要选择奖品等级&#xff08;一等奖、二等奖、三等奖&#xff09;&#xff0c;及奖品库存圈选一批人员参与抽奖 tip&#xff1a;什么时候设置奖品数量和奖品等级&am…

Oracle 深入学习 Part 14:Managing Password Security and Resources(管理密码安全性和资源)

Profiles Profile 是一个以名称标识的集合&#xff0c;用于管理 密码 和 资源限制。 每个用户都对应一个profiles&#xff0c;可以通过 CREATE USER 或 ALTER USER 命令分配给用户。 Profiles 可以启用或禁用。 Profiles 可以关联到默认的 DEFAULT Profile。 密码管理&…