
# 快速开始
本章节以一个被调用API为例，进行检验API中token的合法性。
#### 操作步骤
在一个待集成的应用系统中，找到一个API接口，如*/testApi*。
1. 在工程中增加配置信息，具体配置获取方式见准备工作中收集信息章节。 
   ```
   jwt.service.publickey.url: 公钥获取地址
   jwt.secret.id: 密钥ID
   jwt.secret.appName: 集成应用名称
   jwt.secret.key: 私钥
   jwt.secret.publicKey: 公钥
   ```
   
   
2. 定时加载公钥代码。 
   ```
   public void autoRefreshPublicKey() {
       Calendar calendar = Calendar.getInstance();
       Date currentTime = calendar.getTime();
       Timer timer = new Timer();
       timer.schedule(new TimerTask() {
           @Override
           public void run() {
               try {
                   //定时从IPDCenter获取所有公钥信息
                   List<String> publicKeys = HttpClientUtil.post(url, token);
                   for (String publicKeyStr : publicKeys) {
                       // 公钥加载到内存中
                       PublicKey publicKey = getPublicKey(publicKeyStr);
                   }
               } catch (Exception e) {
                   log.error("autoLoadPublicKey error", e);
               }
           }
       }, currentTime, refreshTime);
   }
   public PublicKey getPublicKey(String publicKeyStr) {
       byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
       X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
       KeyFactory keyFactory;
       try {
           keyFactory = KeyFactory.getInstance("RSA");
           return keyFactory.generatePublic(x509EncodedKeySpec);
       } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
           log.error("Failed to load the public key to the JWT token. Exception: {}", e.getMessage());
       }
       return null;
   }
   ```
   
   
3. 应用启动时加载私钥。 
   ```
   public PrivateKey getPrivateKey(String privateKeyStr) {
       try {
           byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
           PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           return keyFactory.generatePrivate(keySpec);
       } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
           log.error("Failed to load the private key to the JWT token. Exception: {}", e.getMessage());
       }
       return null;
   }
   ```
   
   
4. 检验token的方法。 
   ```
   private static boolean verify(HttpServletRequest httpServletRequest, String publicKeyId, String token) {
       // 从公钥缓存中获取对应的密钥编号的公钥
       PublicKey publicKey = PublicKeyCache.getInstance().publicKeysCache.get(publicKeyId);
       try {
           Algorithm algorithm =  Algorithm.RSA256((RSAPublicKey) publicKey, null);
           DecodedJWT decodedJwt = JWT.require(algorithm).ignoreIssuedAt().build().verify(token);
           Date expiresAt = decodedJwt.getExpiresAt();
           // 验证token是否过期
           if (expiresAt.before(new Date())) {
               LOGGER.error("The token has expired.");
               return false;
           }
           // 验证自己是否为接收方
           List<String> audience = decodedJwt.getAudience();
           if (audience != null && !audience.isEmpty() && !validAudience(httpServletRequest, audience)) {
               return false;
           }
       } catch (JWTVerificationException | IllegalArgumentException | SdkException e) {
           LOGGER.error("Verification failed. Jwt Token verification exception: {}", e.getMessage());
           return false;
       }
       if (LOGGER.isDebugEnabled()) {
           LOGGER.debug("Token has verify successfully.");
       }
       return true;
   }
   ```
   
   
5. 生成token的方法。 
   ```
   public static String generateToken(JwtToken jwtToken, boolean isUnique) {
       // 私钥从缓存中通过编号获取
       PrivateKey privateKey = PrivatekeyCache.getInstance().privateKeysCache.get(jwtToken.getKeyId());
       Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) privateKey);
       Date issuedAt = new Date();
       // 未设置过期时间，则默认签发时间后5分钟内有效
       Date expiresAt =
           new Date(issuedAt.getTime() + (jwtToken.getExpirationTime() <= 0 ? 300000 : jwtToken.getExpirationTime()));
       return "Internal:" + JWT.create()
           .withKeyId(jwtToken.getKeyId())  //密钥ID
           .withIssuer(jwtToken.getIssuer())  //用户名:用户ID
           .withSubject(jwtToken.getSubject())  //appName
           .withExpiresAt(expiresAt)
           .withIssuedAt(issuedAt)
           .withJWTId(jwtToken.getJwtId())  //随机UUID
           .withClaim("claims", jwtToken.getClaimMap())  //保持默认值
           .sign(algorithm);
   }
   ```
   
   
6. 在"/testApi"接口中获取token。 
   ```
   String token = request.getHeader("Authorization");
   ```
   
   
7. 调用检验方法，检验token的合法性，并获取调用者信息。 
   ```
   String issuer = verify(token);
   ```
   
   
 
#### 结果验证
1. 调用SDK中的方法生成一个临时的token。 
   ```
   String token = generateToken();
   ```
   
   
2. 调用API调试工具调用"/testApi"接口，调用时将步骤1中生成的token放入header中。 
   ```
   curl http://ip:port/xx/testApi -H "Authorization:token"
   ```
   
   
 
