JWT验证失败:BAD_SIGNATURE

时间:2018-06-24 04:13:03

标签: java google-app-engine jwt google-cloud-endpoints google-cloud-endpoints-v2

我使用以下文件来遇到问题

https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/appengine-java8/appidentity/src/main/java/com/example/appengine/appidentity/SignForAppServlet.java

编写方法测试以使用App Engine默认服务帐户生成签名的JWT

private String test() throws CertificateException, UnsupportedEncodingException, 
    NoSuchAlgorithmException, InvalidKeyException, SignatureException {

           long now = System.currentTimeMillis() / 1000;

           JSONObject headerJson = new JSONObject();
           headerJson.put("typ", "JWT");
           headerJson.put("alg", "RS256");

           JSONObject payloadJson = new JSONObject();
           payloadJson.put("iat", now);
           payloadJson.put("exp", now + 3600);
           payloadJson.put("iss", "{test-project}@appspot.gserviceaccount.com");
           payloadJson.put("sub", "{test-project}@appspot.gserviceaccount.com");
           payloadJson.put("aud", "https://echo-api.endpoints.{test-project}.cloud.goog");

          String headerAndPayload = String.format("%s.%s", Base64.getUrlEncoder().encodeToString(headerJson.toString().getBytes()), Base64.getUrlEncoder().encodeToString(payloadJson.toString().getBytes()));

          AppIdentityService appIdentityService = AppIdentityServiceFactory.getAppIdentityService();
          AppIdentityService.SigningResult signingResult = appIdentityService.signForApp(headerAndPayload.getBytes());

          String signedJwt = String.format("%s.%s", headerAndPayload , new 
          String(Base64.getUrlEncoder().encode(signingResult.getSignature())));

          return signedJwt;
}

我需要生成签名的JWT来验证在应用引擎中运行的Java后端。使用开放api云端点保护的API。以下是我的openapi.yaml

  swagger: "2.0"
       info:
               description: "A simple Google Cloud Endpoints API example."
       title: "Endpoints Example"
       version: "1.0.0"
       host: "echo-api.endpoints.{test-project}.cloud.goog"

consumes:
            - "application/json"
produces:
            - "application/json"
schemes:
          - "https"

 paths:
         "/test/echo":
          post:
                description: "Echo back a given message."
                operationId: "echo"
          produces:
                  - "application/json"
          responses:
                  200:
          description: "Echo"
          schema:
                   $ref: "#/definitions/echoMessage"
          parameters:
           -
                   description: "Message to echo"
                   in: body
                   name: message
                   required: true
                   schema:
                           $ref: "#/definitions/echoMessage"
                   security:
                          - api_key: []
                            google_jwt: []

       definitions:
                  echoMessage:
                        type: "object"
                        properties:
                        message:
                        type: "string"

       securityDefinitions:
              google_jwt:
              authorizationUrl: ""
              flow: "implicit"
              type: "oauth2"
              x-google-issuer: "stl-cardio-dev@appspot.gserviceaccount.com"
              x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/jwk/{test-project}@appspot.gserviceaccount.com"

创建JWT后,由于“ JWT验证失败:BAD_SIGNATURE”,我尝试访问/ test / echo。

我尝试使用python客户端

https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/clients/service_to_service_gae_default/main.py

我使用以下“标头和有效载荷”和“签名方法”,收到了以下结果。

(01)。 python header_and_payload + python app_identity.sign_blob方法=>成功

(02)。 python header_and_payload + java appIdentity.signForApp()=>错误

(03)。 java headerAndPayload + python app_identity.sign_blob方法=>成功

(04)。 java headerAndPayload + java appIdentity.signForApp()=>错误

我在我的Java实现中看到appIdentity.signForApp()中的问题。

我找不到完整的示例或文档。如何使用Java生成正确的签名JWT。

谢谢。

1 个答案:

答案 0 :(得分:0)

如果没记错,您正在寻找JWT的Java实现。

要生成和验证JWT令牌的最低要求是AlgorithmSecret key

我正在使用JWT的Java实现

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

类文件

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;


...


    public String generateToken(String username) {
        String audience = generateAudience();
        return Jwts.builder()
                .setIssuer( APP_NAME )
                .setSubject(username)
                .setAudience(audience)
                .setIssuedAt(timeProvider.now())
                .setExpiration(generateExpirationDate())
                .signWith( SIGNATURE_ALGORITHM, SECRET )
                .compact();
    }



    private Claims getAllClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            LOGGER.error("Could not get all claims Token from passed token");
            claims = null;
        }
        return claims;
    }

此处 generateToken 将获取所有声明详细信息以及密钥和算法。

getAllClaimsFromToken 用于读取令牌中的详细信息。它基本上验证令牌。 如果有任何错误将相应地引发异常

为此我写了answer。这是工作代码。您可以参考TokenHelper.java以获得更多详细信息