一、背景

公司上架APP到Apple Store,审核被打回,原因是APP中接入了其他第三方登录,所以必须要求接入苹果登录,这项新规定,逼不得已只要接入苹果登录。

二、使用JWT方式接入登录

参考网上很多资料,我看到的都是使用JWT方式接入的,之所以要自己再写一篇同样接入方式的文章,是因为在参考过程中,踩了坑,现在把自己测试成功的方式贴出来,避免后者再踩坑。

1.引入JWT相关工具包

<dependency><groupId>com.auth0</groupId><artifactId>jwks-rsa</artifactId><version>0.12.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.80</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.0</version></dependency>

以上内容是测试demo中引入的内容,如果项目已存在相同的包可以不用重复引入,核心包jjwt、jwks-rsa。

2.请求参数说明

  • IdentityToken:identityToken 是App端请求苹果授权中心拿到的JWT,它由点号“.”分割为三部分,分别是头信息,消息体,签名,前两部分可以通过Base64解码为如下信息。

消息头

{"alg": "ES256","kid": "ABC123DEFG"
}

消息体(仅罗列主要字段)

{"iss": "https://appleid.apple.com","iat": 1437179036,"exp": 1493298100,"aud": "com.mytest.app","sub": "DEF123GHIJ "
}
字段名称 说明
iss 签发机构地址
iat 授权时间戳
exp 过期时间戳
aud bundle id
sub 用户唯一标识

3.Java代码实现
核心工具类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwk.Jwk;
import io.jsonwebtoken.*;
import org.springframework.web.client.RestTemplate;import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.util.Base64;
import java.util.Map;/*** @Classname IOSToeknUtils* @Description IOS token操作工具* @Date 2023/03/23* @Created by Goden*/
public class IOSToeknUtils {private final static String authUrl = "https://appleid.apple.com/auth/keys";private final static String authIss = "https://appleid.apple.com";/*** 解码identityToken* @param identityToken* @return*/public static JSONObject parserIdentityToken(String identityToken) {String[] arr = identityToken.split("\\.");String firstDate = new String(Base64.getDecoder().decode(arr[0]), StandardCharsets.UTF_8);String decode = new String(Base64.getDecoder().decode(arr[1]), StandardCharsets.UTF_8);JSONObject claimObj = JSON.parseObject(decode);// 将第一部分获取到的kid放入消息体中,方便后续匹配对应的公钥使用claimObj.put("kid", JSONObject.parseObject(firstDate).get("kid"));return claimObj;}/*** 根据kid获取对应的苹果公钥* @param kid* @return*/public static PublicKey getPublicKey(String kid) {try {RestTemplate restTemplate = new RestTemplate();JSONObject data = restTemplate.getForObject(authUrl, JSONObject.class);assert data != null;JSONArray jsonArray = data.getJSONArray("keys");for (Object obj : jsonArray) {Map json = ((Map) obj);// 获取kid对应的公钥if (json.get("kid").equals(kid)) {Jwk jwa = Jwk.fromValues(json);return jwa.getPublicKey();}}} catch (Exception e) {}return null;}/*** 对前端传来的identityToken进行验证** @param identityToken* @param jsonObject* @return* @throws Exception*/public static Boolean verifyExc(String identityToken, JSONObject jsonObject) throws Exception {String kid = (String) jsonObject.get("kid");PublicKey publicKey = getPublicKey(kid);JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);jwtParser.requireIssuer(authIss);jwtParser.requireAudience((String) jsonObject.get("aud"));jwtParser.requireSubject((String) jsonObject.get("sub"));try {Jws<Claims> claim = jwtParser.parseClaimsJws(identityToken);if (claim != null && claim.getBody().containsKey("auth_time")) {return true;}return false;} catch (ExpiredJwtException e) {return false;} catch (Exception e) {return false;}}
}

测试类

import com.alibaba.fastjson.JSONObject;/*** @Classname TestIOSLogin* @Description 测试IOS登录* @Date 2023/3/23* @Created by Goden*/
public class TestIOSLogin {public static void main(String[] args) {// 请求的JWTString identityToken = "eyJraWQiOiJlWGF1bm1MIiwiYWxnIjoiUlMyNTYifQ." +"eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmRpeWl5aW4ub25saW5lNTMiLCJl" +"eHAiOjE1OTc2NTAxNzQsImlhdCI6MTU5NzY0OTU3NCwic3ViIjoiMDAxMzc3LmQ0ZDVmMTAwODQ0ZTQzZjdiMWM1O" +"WRiMzUyZWZkZmI4LjAyNTkiLCJjX2hhc2giOiJkTDVRdld2VTNjVHBxczNSazlUTnRBIiwiZW1haWwiOiI0OTk4O" +"TY1MDdAcXEuY29tIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIiwiYXV0aF90aW1lIjoxNTk3NjQ5NTc0LCJub25jZV9" +"zdXBwb3J0ZWQiOnRydWV9." +"hM9HjNsMJW2PjYP7SfbzF-GqOt0VnMjYGq4BoU68rkQ-K2lPp_ae5ziX6Bbr3WHg" +"6cc3Z8OzGO63OfExvSj9gQTR596CZLvNGXhbI3piTK6597-cYsPCTbY7xHxgdHLuL8XhD-9dXPn9rouVYu4QA1" +"8JBQG1Q4sGsRzLEJ5DjOM9x1bkBz4Vu_5LEOefHFHkWN_RPCh_AOJGviDzm81kTkCTWn8jpm0tGdevMR93MOf44" +"f7bjP2T8yezl0Vbv09TrnkdAqG0BsihCD0VN9JV7X2eagyumoxTdFfoRiOflFKAaQqohVzcqy9tHOGm_6w5h8bsR" +"CmtBC4PnqIFqNy_AQ";// 解码后的消息体JSONObject playloadObj = IOSToeknUtils.parserIdentityToken(identityToken);Boolean success;try {success = IOSToeknUtils.verifyExc(identityToken, playloadObj);} catch (Exception e) {throw new RuntimeException(e);}if (!success) {// TODO 校验token失败具体操作return;}// TODO 检验token成功具体业务操作。。。}
}

注意

截止目前,调用接口获取苹果公钥,会返回3个公钥信息,每个公钥信息中都有“kid”这个字段,需要获取解码identityToken头信息中“kid”值匹配的公钥,而不是直接拿返回的公钥数组中第一个公钥来做校验,否者会报如下错误

io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

【JAVA】接入苹果授权登录相关推荐

  1. 【JAVA】对接苹果授权登录流程

    背景 苹果公司要求所有使用第三方登录的 App,都必须接入Sign in with Apple. 接入方式 基于JWT identityToken的算法验证 基于授权码的验证 校验流程 上图为苹果对接 ...

  2. Sign in With Apple (苹果授权登录)

    Sign in With Apple (苹果授权登录) 关于Sign in With Apple (苹果授权登录)的问题,公司app上架appStore被拒原因是使用第三方授权登陆但是却没有使用苹果账 ...

  3. 苹果授权登录Sign In With Apple亲测通过版[100%成功]

    苹果授权登录Sign In With Apple后台代码实现JAVA版本亲测通过版 废话不多说,直接复制把自己的包名写上就可以用了 有个别的小坑,HttpUtil自己写,没附上 Base64一定要用o ...

  4. iOS 苹果授权登录(Sign in with Apple)

    在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. iO ...

  5. Java版本微信授权登录(测试版)

    这篇文章是对微信授权登录的一个测试版本,并不能直接在生产上使用,对于在生产上正式使用将会在下一篇中描述. 一,首先需要以下两个数据 appID和appsecret 如何获取这两个数据,请先登录微信公众 ...

  6. Apple Sign in with Apple(苹果授权登录PHP)

    Apple Sign in with Apple(苹果授权登录PHP) 文章目录 Apple Sign in with Apple(苹果授权登录PHP) 一.登录Apple Developer 二.创 ...

  7. Java版本微信授权登录(升级版)

    前面写了一遍文章<Java版本微信授权登录(测试版)>,可以当做入门的基础文章,这里继续做一点深入,主要解决的是,如何在本地开发中微信授权以后跳转到本地启动的项目中. 我们知道了微信公众平 ...

  8. 第三方接入支付宝授权登录(支付宝新建应用没有公钥和私钥)问题

    由于最近有个需求,需要做第三方的接入支付宝授权登录功能,特此记录下.          百度上很多的接入代码,在此的代码其实和他们差不多,差别在于支付宝官方吧原来的秘钥方式换了,有些同学可能找不到或者 ...

  9. iOS 苹果授权登录(Sign in with Apple)系列之Apple Developer配置篇

    原文 在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. ...

最新文章

  1. android o 全机型推送,氢OS(Android O)官方更新推送 一加两款机型完成适配
  2. 记录一个需求:折线图,要求指定年份每一天的记录
  3. 剑指Offer - 面试题17. 打印从1到最大的n位数
  4. 【秒懂设计模式】单例设计模式
  5. 养鸡农场小程序游戏京东拼多多优惠券附近商家流量主购物源码-修复登录接口
  6. 输液药房管理行业调研报告 - 市场现状分析与发展前景预测
  7. python base64加解密
  8. 洛谷——P2433 【深基1-2】小学数学 N 合一
  9. SDL游戏之路(十一)--按钮制作
  10. 常用汇编指令大全(有注释)
  11. 哪个相机可以拍gif动图_摄制 GIF 动图的相机软件
  12. Threejs实现3d地球记录(5)
  13. 网页调用迅雷的JS(支持客户端版和网页版)
  14. PS改变背景图片/颜色(3种方法)
  15. 9flash:个人网站商业化之蜕
  16. HDU4417 主席树入门2
  17. FTP手机和PC互传文件
  18. 网易我的世界服务器怎么显示键盘,网易我的世界指令怎么用(常见的指令及使用方式)...
  19. 【转载】一封写给有忧国忧民症状的幼稚知识分子的信
  20. 3.Python-复杂数据类型之列表、元组

热门文章

  1. 财务内部收益率用计算机怎么算,用EXCEL计算财务内部收益率
  2. mysql隐藏版本号
  3. 【C++零碎】条件操作符(表达式)—问号(?)
  4. java十进制小数转二进制
  5. SAP中看板触发WM转储TO确认自动关联产生MM物料凭证的控制
  6. spssχ2检验_SPSS详细操作:一致性检验和配对卡方检验
  7. 微博曾近一度衰落后来又再次兴起的原因分别是什么?未来微博又应该怎么发展呢?
  8. There are not enough slots available in the system to satisfy the 4 slots Either request fewer slot
  9. Pandas之数据框运算
  10. springboot 框架计算每个方法执行时间,显示在日志中