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. ASP.NET全局编码和语言

    // /*--------------- // //  使用地方:ASP.NET 项目 // //   // // 文件名: // // 文件功能描述:可控制整个项目的一个统一编码格式和语言文字显示 ...

  2. krpano 全景学习

    krpano 切片工具下载 https://krpano.com/tools/ krpano 案例使用 https://krpano.com/examples/usage/#top krpano  是 ...

  3. 利用Supervisor 管理自己部署的应用程序

    首先,在centos7下安装supervisor yum install python-setuptools easy_install supervisor 然后新建配置文件 #新建superviso ...

  4. 配置vue 多页面

    安装vue 1. 全局安装 vue-cli环境 npm install --global vue-cli 2. 创建一个基于webpack模板的新项目 vue init webpack my-proj ...

  5. Redis 测试 数据类型

  6. Python内置函数系列

    Python内置(built-in)函数随着python解释器的运行而创建.在Python的程序中,你可以随时调用这些函数,不需要定义. 作用域相关(2) locals()  :以字典类型返回当前位置 ...

  7. React/组件通信

    组件通信可以分为以下几种: 父组件向子组件通信 子组件向父组件通信 跨级组件的通信及context 没有嵌套关系的组件通信 父组件向子组件通信   父组件通过props向子组件传递需要的信息.   子 ...

  8. c#NPOI导出2007版本excel

    2003和2007版本区别: HSSFWorkbook(2003) IWorkbook(2007版本) 写完之后会有个问题,导出会报错[流已关闭]. NPOI生产.xlsx文件件时,在使用book.W ...

  9. element-ui组件,全选树节点,新增数据子节点数据,出现回填问题

    案情分析:全选后父节点被选中保存,在这个树节点下新增数据时,就会出现,也被选中,事实上数据是没有被选中,也就意味着权限未被配置,而显示是已经配置了,显然这个是一个bug 1.处理前,直接用下面的方法很 ...

  10. Vue 日期下拉框

    <!-- html --> <template> <!-- 控件样式 --> <div class="select"> <di ...