2019年10月9号  IOS端新增Sign in with Apple

IOS真是世界上最垃圾的语言,没有之一,苹果是世界上最垃圾的公司,没有之一

关于Sign in with Apple 苹果官方给的文档几乎不提后台如何验证,只是画了几张图,客户端把一些参数传递给后台,后台使用这些参数去请求 IOS验证服务器 验证成功 OK 听起来很简单吧

mmp 1.前台给的参数如何解析?

mmp 2.参数怎么传给IOS服务器?

mmp 3.返回什么就算解析成功?

一概不提,最起码给个demo啊

翻遍了网上的资源,最终找到一个还算过的去的 https://blog.csdn.net/wpf199402076118/article/details/99677412

博客中大致说了两种验证方式:

1.JWT 验证 博主也贴出了代码,但是你会发现,代码跑不通,不知道是代码没贴全还是什么鬼,两个方法你不知到怎么调用

2.授权码验证 需要的很多字段你不知道该从哪里获取,前台无法传递给你

经过无数次的试验和无数次的抓狂,最终有了下面的垃圾代码,我总觉得哪里还是有问题,代码贴出来问题接下来说

public static String verify(String jwt, String audience, String subject) throws Exception {
String strkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlxrwmuYSAsTfn+lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu/auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY+RNwCWdjNfEaY/esUPY3OVMrNDI15Ns13xspWS3q+13kdGv9jHI28P87RvMpjz/JCpQ5IM44oSyRnYtVJO+320SB8E2Bw92pmrenbp67KRUzTEVfGU4+obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd/JhmqX5CAaT9Pgi0J8lU/pcl215oANqjy7Ob+VMhug9eGyxAWVfu/1u6QJKePlE+wIDAQAB";
PublicKey publicKey = getPublicKey(strkey);
JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
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 "SUCCESS";
}
return "FIALD";
} catch (ExpiredJwtException e) {
log.error("apple identityToken expired", e);
return "FIALD";
} catch (Exception e) {
log.error("apple identityToken illegal", e);
return "FIALD";
}
} /**
* String转公钥PublicKey
* @param key
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}

说下如何验证

1.IOS客户端会调用苹果的授权登录一系列操作成功后会从苹果那获取一些很基本的信息 比如唯一的userId,一个jwt格式的验证字符串 identityToken,邮箱 等

2.客户端授权验证成功后调用后台接口进行验证

3.后台解析 jwt的这个字符串,jwt格式的字符串用 “ . ”’ 把整个信息分割成三部分,第一部分是 header 包含了 编码格式 和秘钥 id ,第二部分就是一些验证信息 授权人是谁啊 有效时间啊  第三部分是一二部分加起来后再加密的一个东西,这块我也没搞懂,第三部分的解析我到现在也不懂

4. jwt 的 header 和 claim(第二部分) 都是使用Base64编码过的 使用是需要解码

第一部分解析出来的

{
"kid": "AIDOPK1",
"alg": "RS256"
}

第二部分解析出来的

{
"iss": "https://appleid.apple.com",
"aud": "**********",
"exp": 1570617356,
"iat": 1570616756,
"sub": "00*****1790047f40335c6c1a.0641",
"c_hash": "eqOdpr_**TyHiRymHbPQ",
"auth_time": 1570616756
}

5.第二部分的解码可以获取到两个有效信息   aud 和 sub 这两个在验证的时候需要使用

6.验证方法中的key 这个key本来是从苹果提供的一个get接口中获取的但是获取到的格式是下面的东西

{
"keys": [
{
"kty": "RSA",
"kid": "AIDOPK1",
"use": "sig",
"alg": "RS256",
"n": "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w",
"e": "AQAB"
}
]
}

这个东西怎么用?我没要找到具体的描述,但是网上网站可以将这个东西转换正 PublicKey 至于 java代码中如何转换我也没找到,还望找的同学告知下 网上转换后得到的是是一个字符串 通过一下的方法可以转换成 PublicKey

public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}

7.验证 验证字符串的有效时间是5分钟

补充:

String jwt = thirdLoginReq.getIdentityToken();
String decode = Base64.decoded(jwt.split("\\.")[1]);
String substring = decode.substring(0, decode.indexOf("}")+1);
JSONObject jsonObject = JSON.parseObject(substring);
String sub = jsonObject.getString("sub");
String aud = jsonObject.getString("aud");

使用到的jar

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>

更新 20191010 19:00

经过查阅资料发现可以将 苹果返回的公钥转化成 publicKey 需要引入jar包

<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.9.0</version>
</dependency>
     String urlData = getUrlData("https://appleid.apple.com/auth/keys");
Map maps = (Map)JSON.parse(urlData);
List keys = (List<Map>)maps.get("keys");
Map o = (Map) keys.get(0);
Jwk jwa = Jwk.fromValues(o);
try {
PublicKey publicKey = jwa.getPublicKey();
} catch (InvalidPublicKeyException e) {
e.printStackTrace();
}

关于Sign in with Apple 后台验证的一些记录的更多相关文章

  1. Sign in with Apple 流程总结

    流程图 相关说明 UserId 与用户的 Apple Id 一一对应.在同一个开发帐号下的所有 app 里,获取到的值都一样. IdentityToken identityToken 是一个 Json ...

  2. sign in with apple后端校验(java)

    最近新开发的ios平台的app在提审的时候,被拒了,原因是app上如果有接第三方登陆(比如,微信,微博,facebook等),那就必须要接apple id登陆,坑爹~苹果霸权啊!然而没办法,靠他吃饭, ...

  3. SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码

    在SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端 ...

  4. ASP.NET开发中主要的字符验证方法-JS验证、正则表达式、验证控件、后台验证

    ASP.NET开发中主要的字符验证方法-JS验证.正则表达式.验证控件.后台验证 2012年03月19日 星期一 下午 8:53 在ASP.NET开发中主要的验证方法收藏 <1>使用JS验 ...

  5. c#后台验证

    #region 后台验证 panda /// 验证电话号码的主要代码如下: public bool IsTelephone(string str_telephone) { return System. ...

  6. (转)jquery.validate.js 的 remote 后台验证

    之前已经有一篇关于jquery.validate.js验证的文章,还不太理解的可以先看看:jQuery Validate 表单验证(这篇文章只是介绍了一下如何实现前台验证,并没有涉及后台验证remot ...

  7. 表单数据验证方法(二)——ASP.NET后台验证

    昨天写了一下关于如何在前台快捷实现表单数据验证的方法,今天接着昨天的,把后台实现数据验证的方法记录一下.先说明一下哈,我用的是asp.net,所以后台验证方法也是基于.net mvc来做的. 好了,闲 ...

  8. JavaEE 之 后台验证+拦截器

    1.Validator后台验证 a.在web.xml中配置 <listener> <listener-class>org.springframework.web.context ...

  9. asp.net core 图片验证码,后台验证

    验证方法: public static string VerificationCodeCacheFormat="vcode_cache_{0}"; public IActionRe ...

随机推荐

  1. (七)Activiti之历史活动查询和历史任务查询和流程状态查询

    一.历史活动查询 本章案例是基于上一章节案例的基础上,流程走完后进行测试的,也就是下图的流程从学生请假到班主任审批都已经完成,本章用来测试查询历史活动和历史任务的 activiti5的历史活动包括所有 ...

  2. (九) spring 使用自定义限定符注解

    案例一 定义接口  CD.java package interfacepackage; public interface CD { void play(); } 定义接口 player .java p ...

  3. (一)Maven基础及第一个Maven工程

    一.Maven介绍 ANT/Maven/gradle是一个项目管理工具,它包含了一项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecy ...

  4. (一)mybatis介绍

    一.mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

  5. XCode下在不同位置声明变量的用法(转)

    XCode下在不同位置声明变量的用法 方式一:直接在.h文件@interface中的大括号中声明. @interface Test : NSObject { NSString *str; // 私有变 ...

  6. python - pyxel 制作游戏

    之前看了一个项目,觉得还挺有意思的,是关于做一个像素风的游戏,现在,虚幻4,u3d,已经让游戏愈发的好看,好玩,曾经我们童年的像素风游戏,愈来愈少.所以,这里我们就回味下. Pyxel是一个pytho ...

  7. uni-app入门学习

    什么是 uni-app 1 uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS.Android.H5.小程序等多个平台. 官方的体验例子: 2 un ...

  8. 判断对象是否为null

    Person p=teacher as person; If (p!=null ) dostring (); 使用这样的方法效率高 使用 is时 进行两次判断效率低

  9. GNS3 介绍

    什么是GNS3? GNS3是一款模拟CISCO网络设备的模拟器,和CPT(Cisco Packet Tracer)相比.GNS3运行的是真实设备的IOS,命令集更全,在如有部分有非常好的表现,交换部分 ...

  10. Python使用selenium模拟点击,进入下一页(三)

    嗯,昨天呢,我们已经实现了自动输入百度然后搜索Cgrain,然后点击按钮,进入我的页面,在这里呢,有个问题 ActionChains(seleniumGoo).move_by_offset(-480, ...