简单的就是:将前端传来的identity转成用户信息,获取公钥,前两者组装校验
1.获取第一把公钥 https://appleid.apple.com/auth/keys
{ "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"
}
]
}
2.前端传来的jwt,也叫identity(三段式格式),取第二段解码,获取用户信息,aud,sub等,见下面截图
3.根据公钥和第二段解码验证时间是否有效
前端传来的东东
idnetityToken:
eyJraWQiOiJlWGF1bm1MIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLm5lYnVsYS54aW5neXVuY2hvbmciLCJleHAiOjE1OTU5MDIyODksImlhdCI6MTU5NTkwMTY4OSwic3ViIjoiMDAxMDQxLjNiNmU4MDFkMjc1NTQ2MmE4NWNiOWNhOTRkYmI2NmNmLjA2MTkiLCJjX2hhc2giOiJUazJ0a0wwMmpmUUNFbTZ4Sk9heE5BIiwiZW1haWwiOiJsaXJvbmd0YW5vNjAzQGljbG91ZC5jb20iLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJhdXRoX3RpbWUiOjE1OTU5MDE2ODksIm5vbmNlX3N1cHBvcnRlZCI6dHJ1ZX0.fIvXm93mS6AzgtBfcEPj67U0OWxJ1EviS1c3uTR3VnnENLiZih0dyD5b9iXXkKTs9oCpXNzqAedgoHGbX1BUeTyyFI9aWRagS3QO2PusYmKAqiiAgY04jXkl01ThG3apy3sCVWMGEA-FxTZvD8Ku7E9VjHlB9zWGIlsiPzOLlwi9USh_teO5MMChtdbl1sqo9GTKKcZSF0psE2VS0UepAVSA1gdBRq8SU8GOGYdLhV1Ze2TY8_sDUENlrIY74EbA7kEc46WslPHCLPUjT0tAd-vyIo0cB4mJ277jM1MTQvjtT4NGgYwlkJf4TLag7Hz6CNL972n0yWyglgL2HVPJfQ
package com.nebula.microservice.authorization.user.util;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Base64Utils;
import org.springframework.web.client.RestTemplate;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
@Log4j2
public class AppleUtil {
/**
* 解密个人信息
*
* @param identityToken APP获取的identityToken
*
* @return 解密参数:失败返回null sub就是用户id,用户昵称需要前端传过来
*/
public static JSONObject verify(String identityToken) {
try {
String[] identityTokens = identityToken.split("\\.");
String str = new String(Base64Utils.decodeFromString(identityTokens[1]), "UTF-8");
JSONObject data = JSONObject.parseObject(str);
String aud = (String) data.get("aud");
String sub = (String) data.get("sub");
if (verify(identityToken, aud, sub)) {
return data;
}
} catch (Exception e) {
log.info("verify(*) error ",e);
}
return null;
}
/**
* 验证
*
* @param identityToken APP获取的identityToken
* @param aud 您在您的Apple Developer帐户中的client_id
* @param sub 用户的唯一标识符对应APP获取到的:user
* @return true/false
*/
private static boolean verify(String identityToken, String aud, String sub) {
try {
PublicKey publicKey = getPublicKey();
if (publicKey==null){
return false;
}
JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
jwtParser.requireIssuer("https://appleid.apple.com");
jwtParser.requireAudience(aud);
jwtParser.requireSubject(sub);
Jws<Claims> claim = jwtParser.parseClaimsJws(identityToken);
if (claim != null && claim.getBody().containsKey("auth_time")) {
return true;
}
} catch (Exception e) {
log.info("verify(*,*,*) error ", e);
}
return false;
}
private static PublicKey getPublicKey() {
try {
String url = "https://appleid.apple.com/auth/keys";
RestTemplate restTemplate = new RestTemplate();
JSONObject data = restTemplate.getForObject(url,JSONObject.class);
JSONArray jsonArray = data.getJSONArray("keys");
String n = jsonArray.getJSONObject(0).getString("n");
String e = jsonArray.getJSONObject(0).getString("e");
BigInteger modulus = new BigInteger(1, Base64.decodeBase64(n));
BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(e));
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
} catch (Exception e) {
log.info("getPublicKey error ", e);
}
return null;
}
}