【JAVA】接入苹果授权登录
一、背景
公司上架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】接入苹果授权登录相关推荐
- 【JAVA】对接苹果授权登录流程
背景 苹果公司要求所有使用第三方登录的 App,都必须接入Sign in with Apple. 接入方式 基于JWT identityToken的算法验证 基于授权码的验证 校验流程 上图为苹果对接 ...
- Sign in With Apple (苹果授权登录)
Sign in With Apple (苹果授权登录) 关于Sign in With Apple (苹果授权登录)的问题,公司app上架appStore被拒原因是使用第三方授权登陆但是却没有使用苹果账 ...
- 苹果授权登录Sign In With Apple亲测通过版[100%成功]
苹果授权登录Sign In With Apple后台代码实现JAVA版本亲测通过版 废话不多说,直接复制把自己的包名写上就可以用了 有个别的小坑,HttpUtil自己写,没附上 Base64一定要用o ...
- iOS 苹果授权登录(Sign in with Apple)
在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. iO ...
- Java版本微信授权登录(测试版)
这篇文章是对微信授权登录的一个测试版本,并不能直接在生产上使用,对于在生产上正式使用将会在下一篇中描述. 一,首先需要以下两个数据 appID和appsecret 如何获取这两个数据,请先登录微信公众 ...
- Apple Sign in with Apple(苹果授权登录PHP)
Apple Sign in with Apple(苹果授权登录PHP) 文章目录 Apple Sign in with Apple(苹果授权登录PHP) 一.登录Apple Developer 二.创 ...
- Java版本微信授权登录(升级版)
前面写了一遍文章<Java版本微信授权登录(测试版)>,可以当做入门的基础文章,这里继续做一点深入,主要解决的是,如何在本地开发中微信授权以后跳转到本地启动的项目中. 我们知道了微信公众平 ...
- 第三方接入支付宝授权登录(支付宝新建应用没有公钥和私钥)问题
由于最近有个需求,需要做第三方的接入支付宝授权登录功能,特此记录下. 百度上很多的接入代码,在此的代码其实和他们差不多,差别在于支付宝官方吧原来的秘钥方式换了,有些同学可能找不到或者 ...
- iOS 苹果授权登录(Sign in with Apple)系列之Apple Developer配置篇
原文 在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. ...
最新文章
- android o 全机型推送,氢OS(Android O)官方更新推送 一加两款机型完成适配
- 记录一个需求:折线图,要求指定年份每一天的记录
- 剑指Offer - 面试题17. 打印从1到最大的n位数
- 【秒懂设计模式】单例设计模式
- 养鸡农场小程序游戏京东拼多多优惠券附近商家流量主购物源码-修复登录接口
- 输液药房管理行业调研报告 - 市场现状分析与发展前景预测
- python base64加解密
- 洛谷——P2433 【深基1-2】小学数学 N 合一
- SDL游戏之路(十一)--按钮制作
- 常用汇编指令大全(有注释)
- 哪个相机可以拍gif动图_摄制 GIF 动图的相机软件
- Threejs实现3d地球记录(5)
- 网页调用迅雷的JS(支持客户端版和网页版)
- PS改变背景图片/颜色(3种方法)
- 9flash:个人网站商业化之蜕
- HDU4417 主席树入门2
- FTP手机和PC互传文件
- 网易我的世界服务器怎么显示键盘,网易我的世界指令怎么用(常见的指令及使用方式)...
- 【转载】一封写给有忧国忧民症状的幼稚知识分子的信
- 3.Python-复杂数据类型之列表、元组
热门文章
- 财务内部收益率用计算机怎么算,用EXCEL计算财务内部收益率
- mysql隐藏版本号
- 【C++零碎】条件操作符(表达式)—问号(?)
- java十进制小数转二进制
- SAP中看板触发WM转储TO确认自动关联产生MM物料凭证的控制
- spssχ2检验_SPSS详细操作:一致性检验和配对卡方检验
- 微博曾近一度衰落后来又再次兴起的原因分别是什么?未来微博又应该怎么发展呢?
- There are not enough slots available in the system to satisfy the 4 slots Either request fewer slot
- Pandas之数据框运算
- springboot 框架计算每个方法执行时间,显示在日志中