苹果https java_apple登录 后端java实现最终版

import com.alibaba.fastjson.JSONArray;

import com.alibaba.fastjson.JSONObject;

import com.auth0.jwk.Jwk;

import com.helijia.appuser.modules.user.vo.AppleCredential;

import com.helijia.common.api.model.ApiException;

import com.helijia.user.util.HttpClientUtil;

import com.helijia.user.util.UserCode;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.ExpiredJwtException;

import io.jsonwebtoken.Jws;

import io.jsonwebtoken.JwtParser;

import io.jsonwebtoken.Jwts;

import org.apache.commons.lang3.StringUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import org.apache.commons.codec.binary.Base64;

import java.security.PublicKey;

import java.util.Map;

/**

* Created by laohu May 18 2020

*/

@Service

public class AppleService {

private static final Logger LOGGER = LoggerFactory.getLogger(AppleService.class);

private static final String AUTH_URL = "/auth/keys";

@Value("${apple.login.auth.url}")

public String appleUrl;

public void verify(AppleCredential credential) {

try {

String[] identityTokens = credential.getIdentityToken().split("\\.");

Map firstDate = JSONObject

.parseObject(new String(Base64.decodeBase64(identityTokens[0]), "UTF-8"));

Map secondData = JSONObject

.parseObject(new String(Base64.decodeBase64(identityTokens[1]), "UTF-8"));

String kid = String.valueOf(firstDate.get("kid"));

String aud = String.valueOf(secondData.get("aud"));

String sub = String.valueOf(secondData.get("sub"));

// 1.验证apple官方 2.sub和openId的一致性

if (verify(credential.getIdentityToken(), kid, aud, sub)) {

if(StringUtils.isEmpty(credential.getOpenId())) {

credential.setOpenId(sub);

}

return;

}

} catch (Exception e) {

LOGGER.error("apple identityToken verify error", e);

}

throw new ApiException(UserCode.USER_THIRD_ACCESSTOKEN_FAIL.getApiCode(),

UserCode.USER_THIRD_ACCESSTOKEN_FAIL.getApiMessage());

}

/**

* 验证

*

* @param identityToken APP获取的identityToken

* @param aud

* @param sub

* @return true/false

*/

private boolean verify(String identityToken, String kid, String aud, String sub) {

PublicKey publicKey = getPublicKey(kid);

JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);

jwtParser.requireIssuer(appleUrl);

jwtParser.requireAudience(aud);

jwtParser.requireSubject(sub);

try {

Jws claim = jwtParser.parseClaimsJws(identityToken);

if (claim != null && claim.getBody().containsKey("auth_time")) {

return true;

}

return false;

} catch (ExpiredJwtException e) {

LOGGER.error("apple identityToken expired", e);

return false;

} catch (Exception e) {

LOGGER.error("apple identityToken illegal", e);

return false;

}

}

/**

* @param kid 通过kid获取对应的PublicKey

* {

*    "keys": [

*      {

*        "kty": "RSA",

*        "kid": "86D88Kf",

*        "use": "sig",

*        "alg": "RS256",

*        "n": "iGaLqP6y-SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY11qInqUvjJur--hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwCPygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk-ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ",

*        "e": "AQAB"

*      },

*      {

*        "kty": "RSA",

*        "kid": "eXaunmL",

*        "use": "sig",

*        "alg": "RS256",

*        "n": "4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw",

*        "e": "AQAB"

*      }

*    ]

*  }

* @return 构造好的公钥

*/

private PublicKey getPublicKey(String kid) {

try {

String str = HttpClientUtil.get(appleUrl + AUTH_URL);

JSONObject data = JSONObject.parseObject(str);

JSONArray jsonArray = data.getJSONArray("keys");

if(jsonArray.isEmpty()) {

return null;

}

for (Object object : jsonArray) {

JSONObject json = ((JSONObject)object);

if(json.getString("kid").equals(kid)) {

json = ((JSONObject)object);

Jwk jwa = Jwk.fromValues(json);

return jwa.getPublicKey();

}

}

} catch (final Exception e) {

LOGGER.error("apple getPublicKey error", e);

}

return null;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值