百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

在Spring Boot中使用 jose4j 实现 JSON Web Token (JWT)

ztj100 2025-05-14 18:29 27 浏览 0 评论

JSON Web Token 或 JWT 作为服务之间安全通信的一种方式而闻名。

JWT 有两种形式:JWS 和 JWE,它们之间的区别在于 :

JWS 的有效载荷(通讯的内容)没有加密,而 JWE 是加密的。

本文将探讨 Java Spring Boot 中 JWT 的实现,学习使用jose4j在Java中创建JWS和JWE。

本文中的代码托管在以下 GitHub 存储库中: https
://github.com/brilianfird/jwt-demo

jose4j是 Java 中流行的 JWT 库之一,具有完整的功能。

<dependency>   
    <groupId>org.bitbucket.b_c</groupId>   
    <artifactId>jose4j</artifactId>   
    <version>0.7.12</version>   
</dependency>

JSON Web Signature (JWS) 由三部分组成:

  • JOSE 标头
  • Payload有效载荷
  • 签名

JOSE 标头:

{
    alg:<font>"HS264"</font><font>
}
</font>

JOSE 标头存储有关如何处理 JWS 的元数据。alg存储有关 JWT 使用哪种签名算法的信息。

接下来,让我们检查有效载荷:

{ 
  “sub”:“1234567890”,
  “name”:“Brilian Firdaus”,
  “iat”:1651422365 
}

JSON 有效载荷存储我们要传输到客户端的数据。它还存储了一些 JWT 声明,以供我们验证。

在上面的示例中,我们将三个字段注册为 JWT 声明。

  • sub表示用户的唯一id
  • name表示用户名
  • iat表示我们在一个 epoch 中创建 JWT 的时间

最后一部分是签名,它是使 JWS 安全的部分。通常,JWS 的签名将采用字节的形式。

让我们看一个 Base64 编码签名的示例:

qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI

现在,如果我们看到上面的三个部分,您可能想知道如何将这三个部分无缝地传递给消费者。

答案是紧凑的序列化。使用紧凑序列化,我们可以轻松地与消费者共享 JWS,因为 JWS 将成为一个长字符串。

Base64.encode(JOSE 标头) + <font>"."</font><font> + Base64.encode(有效负载)+“。” + Base64.encode(签名)
</font>

结果将是:

eyJhbGciOiJIUzI1NiIsImtpZCI6IjIwMjItMDUtMDEifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJyaWxpYW4gRmlyZGF1cyIsImlhdCI6MTY1MTQyMjM2NX0.qsg3HKPxM96PeeXl-sMraoBy00

紧凑序列化部分在 JWT 规范中也是强制性的。所以为了让 JWS 被认为是 JWT,我们必须进行紧凑的序列化。

未受保护

我们将探讨的第一种 JWS 是不受保护的 JWS。人们很少使用这种类型的 JWS(基本上只是一个常规的 JSON),但让我们首先探索一下以了解实现的基础。

让我们从创建标头开始。与之前使用算法的示例不同HS256,现在我们将不使用算法。

生成不受保护的 JWS:

@Test  
<b>public</b> <b>void</b> JWS_noAlg() throws Exception {  
  
  JwtClaims jwtClaims = <b>new</b> JwtClaims();  
  jwtClaims.setSubject(<font>"7560755e-f45d-4ebb-a098-b8971c02ebef"</font><font>); </font><font><i>// set sub</i></font><font>
  jwtClaims.setIssuedAtToNow();  </font><font><i>// set iat</i></font><font>
  jwtClaims.setExpirationTimeMinutesInTheFuture(10080); </font><font><i>// set exp</i></font><font>
  jwtClaims.setIssuer(</font><font>"https://codecurated.com"</font><font>); // set iss
  jwtClaims.setStringClaim(</font><font>"name"</font><font>, </font><font>"Brilian Firdaus"</font><font>);   </font><font><i>// set name</i></font><font>
  jwtClaims.setStringClaim(</font><font>"email"</font><font>, </font><font>"brilianfird@gmail.com"</font><font>);</font><font><i>//set email  </i></font><font>
  jwtClaims.setClaim(</font><font>"email_verified"</font><font>, <b>true</b>);  </font><font><i>//set email_verified</i></font><font>
  
  JsonWebSignature jws = <b>new</b> JsonWebSignature();  
  jws.setAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS);  
  jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.NONE);  
  jws.setPayload(jwtClaims.toJson());  
  
  String jwt = jws.getCompactSerialization(); </font><font><i>//produce eyJ.. JWT</i></font><font>
  System.out.println(</font><font>"JWT: "</font><font> + jwt);  
}
</font>

让我们看看我们在代码中做了什么:

  • 我们设置了一堆声明(sub, iat, exp, iss, name, email, email_verified)
  • 我们将签名算法设置为NONE,算法约束设置为,NO_CONSTRAINT因为jose4j会抛出异常,因为算法缺乏安全性
  • 我们将 JWS 打包在紧凑序列化中,它将生成一个包含 JWS 的字符串。结果是一个 JWT 编译的字符串。

让我们看看我们通过调用
jws.getCompactSerialization()得到什么输出:

eyJhbGciOiJub25lIn0.eyJzdWIiOiI3NTYwNzU1ZS1mNDVkLTRlYmItYTA5OC1iODk3MWMwMmViZWYiLCJpYXQiOjE2NTI1NTYyNjYsImV4cCI6MTY1MzE2MTA2NiwiaXNzIjoiaHR0cHM6Ly9jb2RlY3VyYXRlZC5jb20iLCJuYW1lIjoiQnJpbGlhbiBGaXJkYXVzIiwiZW1haWwiOiJicmlsaWFuZmlyZEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.

如果我们尝试对其进行解码,我们将获得带有我们之前设置的字段的 JWS:

{
  <font>"header"</font><font>: {
    </font><font>"alg"</font><font>: </font><font>"none"</font><font>
  },
  </font><font>"payload"</font><font>: {
    </font><font>"sub"</font><font>: </font><font>"7560755e-f45d-4ebb-a098-b8971c02ebef"</font><font>,
    </font><font>"iat"</font><font>: 1652556266,
    </font><font>"exp"</font><font>: 1653161066,
    </font><font>"iss"</font><font>: </font><font>"https://codecurated.com"</font><font>,
    </font><font>"name"</font><font>: </font><font>"Brilian Firdaus"</font><font>,
    </font><font>"email"</font><font>: </font><font>"brilianfird@gmail.com"</font><font>,
    </font><font>"email_verified"</font><font>: <b>true</b>
  }
}
</font>

我们已经成功地使用 Javajose4j库创建了 JWT!

现在,让我们继续 JWT 使用的过程。

要使用 JWT,我们可以使用库JwtConsumer中的类jose4j。让我们看一个例子:

@Test  
<b>public</b> <b>void</b> JWS_consume() throws Exception {  
  String jwt = <font>"eyJhbGciOiJub25lIn0.eyJzdWIiOiI3NTYwNzU1ZS1mNDVkLTRlYmItYTA5OC1iODk3MWMwMmViZWYiLCJpYXQiOjE2NTI1NTYyNjYsImV4cCI6MTY1MzE2MTA2NiwiaXNzIjoiaHR0cHM6Ly9jb2RlY3VyYXRlZC5jb20iLCJuYW1lIjoiQnJpbGlhbiBGaXJkYXVzIiwiZW1haWwiOiJicmlsaWFuZmlyZEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0."</font><font>;  
  
  JwtConsumer jwtConsumer = <b>new</b> JwtConsumerBuilder()  
          </font><font><i>// required for NONE alg  </i></font><font>
          .setJwsAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS) 
          </font><font><i>// disable signature requirement  </i></font><font>
          .setDisableRequireSignature()
          </font><font><i>// require the JWT to have iat field  </i></font><font>
          .setRequireIssuedAt() 
          </font><font><i>// require the JWT to have exp field </i></font><font>
          .setRequireExpirationTime()  
          </font><font><i>// expect the iss to be https://codecurated.com  </i></font><font>
          .setExpectedIssuer(</font><font>"https://codecurated.com"</font><font>) 
          .build();  
          
  </font><font><i>// process JWT to jwt context  </i></font><font>
  JwtContext jwtContext = jwtConsumer.process(jwt); 
  </font><font><i>// get JWS object</i></font><font>
  JsonWebSignature jws = (JsonWebSignature)jwtContext.getJoseObjects().get(0);
  </font><font><i>// get claims  </i></font><font>
  JwtClaims jwtClaims = jwtContext.getJwtClaims(); 
  
  </font><font><i>// print claims as map  </i></font><font>
  System.out.println(jwtClaims.getClaimsMap()); 
}
</font>

通过使用JwtConsumer,我们可以轻松地制定有关在处理传入 JWT 时要验证的内容的规则。通过.getJoseObjects()和getJwtClaims()方法实现了一种简单的方法分别来获取 JWS 对象和声明。

现在我们知道如何在没有签名算法的情况下生成和使用 JWT,使用它来理解 JWT 会容易得多。

不同之处在于我们需要设置算法并创建一个密钥来生成/验证 JWT。

HMAC SHA-256

HMAC SHA-256(HS256)是一个具有对称密钥的MAC函数。我们需要为它的秘钥生成至少32个字节,并将其送入jose4j库中的HmacKey类以确保安全。

我们将使用Java中的SecureRandom库来确保密钥的随机性。

byte[] key = <b>new</b> byte[32];  
  
SecureRandom secureRandom = <b>new</b> SecureRandom();  
secureRandom.nextBytes(key);

HmacKey hmacKey = <b>new</b> HmacKey(key);

密钥应被视为一种凭证。因此,它应该被存储在一个安全的环境中。作为建议,你可以将其作为环境变量或存储在[Vault](
https://www.vaultproject.io/)中。

让我们看看如何创建和使用用HS256签名的JWT。

@Test  
<b>public</b> <b>void</b> JWS_HS256() throws Exception {  
    
  <font><i>// generate  key  </i></font><font>
  byte[] key = <b>new</b> byte[32];  
  SecureRandom secureRandom = <b>new</b> SecureRandom();  
  secureRandom.nextBytes(key);  
  HmacKey hmacKey = <b>new</b> HmacKey(key);  
  
  JwtClaims jwtClaims = <b>new</b> JwtClaims();  
  jwtClaims.setSubject(</font><font>"7560755e-f45d-4ebb-a098-b8971c02ebef"</font><font>); </font><font><i>// set sub  </i></font><font>
  jwtClaims.setIssuedAtToNow();  </font><font><i>// set iat  </i></font><font>
  jwtClaims.setExpirationTimeMinutesInTheFuture(10080); </font><font><i>// set exp  </i></font><font>
  jwtClaims.setIssuer(</font><font>"https://codecurated.com"</font><font>); // set iss  
  jwtClaims.setStringClaim(</font><font>"name"</font><font>, </font><font>"Brilian Firdaus"</font><font>);   </font><font><i>// set name  </i></font><font>
  jwtClaims.setStringClaim(</font><font>"email"</font><font>, </font><font>"brilianfird@gmail.com"</font><font>);</font><font><i>//set email  </i></font><font>
  jwtClaims.setClaim(</font><font>"email_verified"</font><font>, <b>true</b>);  </font><font><i>//set email_verified  </i></font><font>
  
  JsonWebSignature jws = <b>new</b> JsonWebSignature();  
  </font><font><i>// Set alg header as HMAC_SHA256  </i></font><font>
  jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);  
  </font><font><i>// Set key to hmacKey  </i></font><font>
  jws.setKey(hmacKey);  
  jws.setPayload(jwtClaims.toJson());  
  
  String jwt = jws.getCompactSerialization(); </font><font><i>//produce eyJ.. JWT  </i></font><font>
  
  </font><font><i>// we don't need NO_CONSTRAINT and disable require signature anymore </i></font><font>
  JwtConsumer jwtConsumer = <b>new</b> JwtConsumerBuilder()  
          .setRequireIssuedAt()  
          .setRequireExpirationTime()  
          .setExpectedIssuer(</font><font>"https://codecurated.com"</font><font>)  
          </font><font><i>// set the verification key  </i></font><font>
          .setVerificationKey(hmacKey)  
          .build();  
  
  </font><font><i>// process JWT to jwt context  </i></font><font>
  JwtContext jwtContext = jwtConsumer.process(jwt);  
  </font><font><i>// get JWS object  </i></font><font>
  JsonWebSignature consumedJWS = (JsonWebSignature)jwtContext.getJoseObjects().get(0);  
  </font><font><i>// get claims  </i></font><font>
  JwtClaims consumedJWTClaims = jwtContext.getJwtClaims();  
  
  </font><font><i>// print claims as map  </i></font><font>
  System.out.println(consumedJWTClaims.getClaimsMap());  
  
  </font><font><i>// Assert header, key, and claims  </i></font><font>
  Assertions.assertEquals(jws.getAlgorithmHeaderValue(), consumedJWS.getAlgorithmHeaderValue());  
  Assertions.assertEquals(jws.getKey(), consumedJWS.getKey());  
  Assertions.assertEquals(jwtClaims.toJson(), consumedJWTClaims.toJson());  
}
</font>

与创建一个没有签名算法的JWS相比,代码上并没有太大的区别。我们首先使用SecureRandom和HmacKey类制作密钥。由于HS256使用对称密钥,我们只需要一个密钥,我们将用它来签署和验证JWT。

我们还通过使用
jws.setAlgorithmheaderValue(
AlgorithmIdentifiers.HMAC_SHA256)将算法头值设置为HS256,并使用jws.setKey(hmacKey)设置密钥。

在JWT的使用消费者中,我们只需要通过在jwtConsumer对象上使用.setVerificationKey(hmacKey)来设置HMAC密钥,jose4j将通过解析JWS的JOSE头来自动确定在JWS中使用何种算法。

ES256

与只需要一个密钥的HS256不同,我们需要为ES256算法生成两个密钥:私钥和公钥。

我们可以使用私钥来创建和验证JWT,而我们只能使用公钥来验证JWT。由于这些特性,私钥通常被存储为凭证,而公钥可以作为JWK托管在公共场合,这样JWT的消费者就可以自己查询主机并获得密钥。

jose4j库提供了一个简单的API来生成私钥和公钥作为JWK。

EllipticCurveJsonWebKey ellipticCurveJsonWebKey = EcJwkGenerator.generateJwk(EllipticCurves.P256);

<font><i>// get private key</i></font><font>
ellipticCurveJsonWebKey.getPrivateKey();

</font><font><i>// get public key</i></font><font>
ellipticCurveJsonWebKey.getECPublicKey();
</font>

现在我们知道了如何生成密钥,用ES256算法创建JWT,这与用HS256算法创建JWT几乎一样。

...
JsonWebSignature jws = <b>new</b> JsonWebSignature();  
<font><i>// Set alg header as ECDSA_USING_P256_CURVE_AND_SHA256  </i></font><font>
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);  
</font><font><i>// Set key to the generated private key  </i></font><font>
jws.setKey(ellipticCurveJsonWebKey.getPrivateKey());  
jws.setPayload(jwtClaims.toJson());
...
JwtConsumer jwtConsumer = <b>new</b> JwtConsumerBuilder()  
        .setRequireIssuedAt()  
        .setRequireExpirationTime()  
        .setExpectedIssuer(</font><font>"https://codecurated.com"</font><font>)  
        </font><font><i>// set the verification key as the public key  </i></font><font>
        .setVerificationKey(ellipticCurveJsonWebKey.getECPublicKey())  
        .build();
...
</font>

唯一不同的地方是。

  • 我们将算法头设置为ECDSA_USING_P256_CURVE_AND_SHA256
  • 我们在创建JWT时使用私钥
  • 我们使用公钥来验证JWT

托管JWK

我们可以使用JsonWebKeySet类轻松创建JSON网络密钥集。

@GetMapping(<font>"/jwk"</font><font>)  
<b>public</b> String jwk() throws JoseException {  
</font><font><i>// Create public key and private key pair</i></font><font>
  EllipticCurveJsonWebKey ellipticCurveJsonWebKey = EcJwkGenerator.generateJwk(EllipticCurves.P256);  
  
  </font><font><i>// Create JsonWebkeySet object</i></font><font>
  JsonWebKeySet jsonWebKeySet = <b>new</b> JsonWebKeySet();  

  </font><font><i>// Add the public key to the JsonWebKeySet object</i></font><font>
  jsonWebKeySet.addJsonWebKey(ellipticCurveJsonWebKey);  

  </font><font><i>// toJson() method by default won't host the private key</i></font><font>
  <b>return</b> jsonWebKeySet.toJson();  
}
</font>

我们还需要改变密钥解析器的一些属性。

<font><i>// Define verification key resolver</i></font><font>
HttpsJwks httpsJkws = <b>new</b> HttpsJwks(</font><font>"http://localhost:8080/jwk"</font><font>);  
HttpsJwksVerificationKeyResolver verificationKeyResolver =  
    <b>new</b> HttpsJwksVerificationKeyResolver(httpsJkws);  
  
JwtConsumer jwtConsumer = <b>new</b> JwtConsumerBuilder()  
    .setRequireIssuedAt()  
    .setRequireExpirationTime()  
    .setExpectedIssuer(</font><font>"https://codecurated.com"</font><font>)  
    </font><font><i>// set verification key resolver</i></font><font>
    .setVerificationKeyResolver(verificationKeyResolver)  
    .build();
</font>

由于我们托管了JSON网络密钥集,我们需要查询主机。jose4j也通过使用
HttpsJwksVerificationKeyResolver提供了一个简单的方法来实现。

在Java中实现JWE

与JWS不同,JSON Web加密是JWT的一种类型,它是经过加密的,除了拥有私钥的人,没有人可以看到它的内容。首先,让我们看看它的一个例子。

eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiMEdxMEFuWUk1RVFxOUVZYjB4dmxjTGxKanV6ckxhSjhUdHYzk5MU9sayIsInkiOiJya1Q2cjlqUWhjRU1xaGtubHJ6S0hVemFKMlhWakFpWGpIWGZZU9aY0hRIiwiY3J2IjoiUC0yNTYifX0。 DUrC7Y_ejpt1n9c8wXetwU65sxkEYxG6RBsCUdokVODJBtwypL9VjQ.ydZx-UDWDN7jbGeESXvPHg.6 ksHUeeGgGj0txFNXmsSQUCnAv52tJuGR5vgrX54vnLkryPFv2ATdLwYXZz3mAjeDes4s9otz4-Fzg1IBZ4qsfCVa6_3CVdkb8BTU4OvQx23SFEgtj8zh-8ZrqZbpKIT.p-E09mQIleNCCmwX3YL-uQ

JWE的结构是:

BASE64URL(UTF8(JWE Protected Header)) || ’.’ ||
BASE64URL(JWE Encrypted Key) || ’.’ ||
BASE64URL(JWE Initialization Vector) || ’.’ ||
BASE64URL(JWE Ciphertext) || ’.’ ||
BASE64URL(JWE Authentication Tag)

而如果我们解密JWE,我们将得到以下的内容。

{
    <font>"iss"</font><font>: </font><font>"https://codecurated.com"</font><font>。
    </font><font>"exp"</font><font>:1654274573。
    </font><font>"iat"</font><font>:1654256573。
    </font><font>"sub"</font><font>: </font><font>"12345"</font><font>
}
</font>

下面看看如何创建JWE::

@Test  
<b>public</b> <b>void</b> JWE_ECDHES256() throws Exception {  
  <font><i>// Determine signature algorithm and encryption algorithm  </i></font><font>
  String alg = KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW;  
  String encryptionAlgorithm = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;  
  
  </font><font><i>// Generate EC JWK  </i></font><font>
  EllipticCurveJsonWebKey ecJWK = EcJwkGenerator.generateJwk(EllipticCurves.P256);  
  
  </font><font><i>// Create  </i></font><font>
  JwtClaims jwtClaims = <b>new</b> JwtClaims();  
  jwtClaims.setIssuer(</font><font>"https://codecurated.com"</font><font>);  
  jwtClaims.setExpirationTimeMinutesInTheFuture(300);  
  jwtClaims.setIssuedAtToNow();  
  jwtClaims.setSubject(</font><font>"12345"</font><font>);  
  
  </font><font><i>// Create JWE  </i></font><font>
  JsonWebEncryption jwe = <b>new</b> JsonWebEncryption();  
  jwe.setPlaintext(jwtClaims.toJson());  
  
  </font><font><i>// Set JWE's signature algorithm and encryption algorithm  </i></font><font>
  jwe.setAlgorithmHeaderValue(alg);  
  jwe.setEncryptionMethodHeaderParameter(encryptionAlgorithm);  
  
  </font><font><i>// Unlike JWS, to create the JWE we use the public key  </i></font><font>
  jwe.setKey(ecJWK.getPublicKey());  
  String compactSerialization = jwe.getCompactSerialization();  
  System.out.println(compactSerialization);  
  
  </font><font><i>// Create JWT Consumer  </i></font><font>
  JwtConsumer jwtConsumer =  
      <b>new</b> JwtConsumerBuilder()  
          </font><font><i>// We set the private key as decryption key  </i></font><font>
          .setDecryptionKey(ecJWK.getPrivateKey())  
          </font><font><i>// JWE doesn't have signature, so we disable it  </i></font><font>
          .setDisableRequireSignature()  
          .build();  
  
  </font><font><i>// Get the JwtContext of the JWE  </i></font><font>
  JwtContext jwtContext = jwtConsumer.process(compactSerialization);  
  
  System.out.println(jwtContext.getJwtClaims());  
}
</font>

与JWS相比,创建和消费JWE的主要区别是。

  • 我们使用公钥作为加密密钥,使用私钥作为解密密钥
  • 我们在JWE中没有签名,所以消费者将需要跳过签名要求

总结

在这篇文章中,我们已经学会了使用jose4j在Java中创建JWS和JWE。

相关推荐

人生苦短,我要在VSCode里面用Python

轻沉发自浅度寺量子位出品|公众号QbitAI在程序员圈子里,VisualStudioCode(以下简称VSCode)可以说是目前最火的代码编辑器之一了。它是微软出品的一款可扩展的轻量...

亲测可用:Pycharm2019.3专业版永久激活教程

概述随着2020年的到来,又有一批Pycharm的激活码到期了,各位同仁估计也是在到处搜索激活方案,在这里,笔者为大家收录了一个永久激活的方案,亲测可用,欢迎下载尝试:免责声明本项目只做个人学习研究之...

Python新手入门很简单(python教程入门)

我之前学习python走过很多的歧途,自学永远都是瞎猫碰死耗子一样,毫无头绪。后来心里一直都有一个做头条知识分享的梦,希望自己能够帮助曾经类似自己的人,于是我来了,每天更新5篇Python文章,喜欢的...

Pycharm的设置和基本使用(pycharm运行设置)

这篇文章,主要是针对刚开始学习python语言,不怎么会使用pycharm的童鞋们;我来带领大家详细了解下pycharm页面及常用的一些功能,让大家能通过此篇文章能快速的开始编写python代码。一...

依旧是25年最拔尖的PyTorch实用教程!堪比付费级内容!

我真的想知道作者到底咋把PyTorch教程整得这么牛的啊?明明在内容上已经足以成为付费教材了,但作者偏要免费开源给大家学习!...

手把手教你 在Pytorch框架上部署和测试关键点人脸检测项目DBFace

这期教向大家介绍仅仅1.3M的轻量级高精度的关键点人脸检测模型DBFace,并手把手教你如何在自己的电脑端进行部署和测试运行,运行时bug解决。01.前言前段时间DBFace人脸检测库横空出世,...

进入Python的世界02外篇-Pycharm配置Pyqt6

为什么这样配置,要开发带UI的python也只能这样了,安装过程如下:一安装工具打开终端:pipinstallPyQt6PyQt6-tools二打开设置并汉化点击plugin,安装汉化插件,...

vs code如何配置使用Anaconda(vscode调用anaconda库)

上一篇文章中(Anaconda使用完全指南),我们能介绍了Anaconda的安装和使用,以及如何在pycharm中配置Anaconda。本篇,将继续介绍在vscode中配置conda...

pycharm中conda解释器无法配置(pycharm配置anaconda解释器)

之前用的好好的pycharm正常配置解释器突然不能用了?可以显示有这个环境然后确认后可以conda正在配置解释器,但是进度条结束后还是不成功!!试过了pycharm重启,pycharm重装,anaco...

Volta:跨平台开发者的福音,统一前端js工具链从未如此简单!

我们都知道现在已经进入了Rust时代,不仅很多终端常用的工具都被rust重写了,而且现在很多前端工具也开始被Rust接手了,这不,现在就出现了一款JS工具管理工具,有了它,你可以管理多版本的js工具,...

开发者的福音,ElectronEgg: 新一代桌面应用开发框架

今天给大家介绍一个开源项目electron-egg。如果你是一个JS的前端开发人员,以前面对这项任务桌面应用开发在时,可能会感到无从下手,甚至觉得这是一项困难的挑战。ElectronEgg的出现,它能...

超强经得起考验的低代码开发平台Frappe

#挑战30天在头条写日记#开始进行管理软件的开发来讲,如果从头做起不是不可以,但选择一款免费的且经得起时间考验的低代码开发平台是非常有必要的,将大幅提升代码的质量、加快开发的效率、以及提高程序的扩展性...

一文带你搞懂Vue3 底层源码(vue3核心源码解析)

作者:妹红大大转发链接:https://mp.weixin.qq.com/s/D_PRIMAD6i225Pn-a_lzPA前言vue3出来有一段时间了。今天正式开始记录一下梗vue3.0.0-be...

Windows 11 + WSL2 打造轻量级 Linux 本地开发环境实战教程

一、前言...

基于小程序 DSL(微信、支付宝)的,可扩展的多端研发框架

Mor(发音为/mr/,类似more),是饿了么开发的一款基于小程序DSL的,可扩展的多端研发框架,使用小程序原生DSL构建,使用者只需书写一套(微信或支付宝)小程序,就可以通过Mor...

取消回复欢迎 发表评论: