java苹果登录token校验工具类

maven依赖

            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>jwks-rsa</artifactId>
                <version>0.9.0</version>
            </dependency>

java工具类

/**
 * 苹果登录工具类
 * @author qinweipeng
 * @Description
 * @create 2020-07-23 15:18
 */
public class AppleLoginUtil {

    /**
     * 获取苹果公钥
     * 此处可能返回多个公钥,根据identifyToken中header中的kid来定位并生成对应的publicKey
     * @return
     */
    public static List<ApplePublicKey> getApplePublicKey() {
        String httpResult = new String(HttpsUtil.doGet("https://appleid.apple.com/auth/keys"));
        if (StringUtils.isBlank(httpResult)) {
            throw new BusinessException("获取公钥失败");
        }
        AppleAuthKeysResponse appleAuthKeysResponse = JsonUtil.fromJson(httpResult, AppleAuthKeysResponse.class);
        return appleAuthKeysResponse.getKeys();
    }

    /**
     * 生成公钥
     * @param applePublicKey ApplePublicKey 转map
     * @return
     * @throws InvalidPublicKeyException
     */
    public static PublicKey genPublicKey(Map<String, Object> applePublicKey) throws InvalidPublicKeyException {
        Jwk jwa = Jwk.fromValues(applePublicKey);
        return jwa.getPublicKey();
    }

    /**
     * 验证
     * @param key
     * @param jwt
     * @param audience
     * @param subject
     * @return
     */
    public static boolean verify(PublicKey key, String jwt, String audience, String subject) {
        JwtParser jwtParser = Jwts.parser().setSigningKey(key);
        jwtParser.requireIssuer("https://appleid.apple.com");
        jwtParser.requireAudience(audience);
        jwtParser.requireSubject(subject);
        try {
            Jws<Claims> claim = jwtParser.parseClaimsJws(jwt);
            if (claim != null && claim.getBody().containsKey("auth_time")) {
                return true;
            }
            return false;
        } catch (ExpiredJwtException e) {
            throw new BusinessException("苹果token过期", e);
        } catch (Exception e) {
            throw new BusinessException("非法token", e);
        }
    }

    /**
     * 验证token
     * @return 苹果用户唯一编码
     */
    public static String verifyIdentityToken(String identityToken){
        if (identityToken.split("\\.").length <= 1) {
            throw new BusinessException("不合法的token");
        }
        List<ApplePublicKey> applePublicKeys = getApplePublicKey();
        Map<String, List<ApplePublicKey>> applePublicKeyMap = applePublicKeys.stream().collect(Collectors.groupingBy(ApplePublicKey::getKid));
        String headStr = new String(Base64.decodeBase64(identityToken.split("\\.")[0]));
        String claimStr = new String(Base64.decodeBase64(identityToken.split("\\.")[1]));
        AppleTokenHead head = JsonUtil.fromJson(headStr, AppleTokenHead.class);
        AppleTokenClaims claims = JsonUtil.fromJson(claimStr, AppleTokenClaims.class);
        List<ApplePublicKey> publicKeys = applePublicKeyMap.get(head.getKid());
        if (CollectionUtils.isEmpty(publicKeys)) {
            throw new BusinessException("未获取到合法密钥,登录失败");
        }
        ApplePublicKey publicKey = publicKeys.get(0);
        Map<String, Object> map = (Map<String, Object>) JsonUtil.jsonToMap(JsonUtil.objectToJson(publicKey));
        try {
            PublicKey key = genPublicKey(map);
            if (verify(key, identityToken, claims.getAud(), claims.getSub())) {
                return claims.getSub();
            } else {
                throw new BusinessException("token验证失败");
            }
        } catch (InvalidPublicKeyException e) {
            throw new BusinessException("不合法的密钥", e);
        }
    }

}

用到的bean:

@Data
public class AppleAuthKeysResponse {

    private List<ApplePublicKey> keys;

}
@Data
public class ApplePublicKey {

    private String kty;

    private String kid;

    private String use;

    private String alg;

    private String n;

    private String e;


}
@Data
public class AppleTokenClaims {

    /**
     * 苹果签发
     */
    private String iss;

    /**
     * APP ID
     */
    private String aud;

    private String exp;

    private String iat;

    /**
     * 用户唯一标识
     */
    private String sub;

    private String c_hash;

    private String auth_time;

}
@Data
public class AppleTokenHead {

    /**
     * 对应密钥中的kid
     */
    private String kid;

    /**
     * 加密算法
     */
    private String alg;

}

 

http工具类、json工具类、自定义异常等请自行处理;

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值