前言
首先介绍一下为什么写这篇文章。最近,公司有一个项目,是海外的手机游戏想要上到云平台上供各种客户端(web,Android,ios等)可以无需下载游戏即可游玩。其中我负责web端的项目,项目需要接入第三方登录,Google、Apple、FaceBook三种方式登录。在我做项目的准备工作期间,我发现网上的web端接入Apple登录的文档特别少,几乎没有...... 所以我打算通过官方文档和一些“简单”的方法实现后发表这篇文章,以便于后续接触到这种场景的人可以通过这篇文章解决你的问题!! 最后说一句:由于项目有点紧急,所以代码的一些不规范和注释少还请谅解,当然我会尽可能说明代码用处啥的~。
官方文档和一些对我有用的帖子
JSON Web 令牌库 - jwt.io (用于生成client_secret)
java 操作 Cookie 跨域(同顶级域名)_huaism的博客-CSDN博客
help in java_java 后端 sign in with apple 随笔_汤一白君的博客-CSDN博客
Sign in with Apple NODE,web端接入苹果第三方登录 – 前端开发,JQUERY特效,全栈开发,vue开发
苹果授权登录(Sign in with Apple)-JAVA后端开发_KaisonChen的博客-CSDN博客
以上这些文档和工具,就是我在开发过程中,所找到的一些较为有用的工具。可以提取不少信息。可能还有一些我用到的帖子,不过我给忘了,就没贴出来了。
步骤
一、首先是需要申请Apple开发者账号,以及配置一些参数。
这个步骤我就不再赘述了,帖子栏最后一条链接里有步骤。
二、获取一些必要的参数。
当申请、配置好开发者账号后,我们需要获取一些必要参数。
这些是我后端所用到的所有参数。
1. KID
官方文档的解释:
用于生成JWT(client_secret)的一个参数,大小为10个字符串。
例如:
KID = "KOI98S78J6";
2. TEAM_ID (iss)
官方文档的解释:
用于生成JWT(client_secret)的一个参数,大小为10个字符串。
例如:
TEAM_ID = "JI87S9KI7D";
3. CLIENT_ID
即apple的应用id,一般是域名的反写。
例如:
CLIENT_ID = "com.example.signservice";
4. PRIVATE_KEY
代码中拼写错误,是Private_key(私钥),是以.p8结尾的文本文件,用作生成JWT,是作为请求Token时的参数之一;
改后缀为.txt
图片打码部分是你的KID,请核对好;
然后以txt文件类型打开这个文件,如下图:
全部复制或者只复制中间的字符串都可,中间的字符串就是你的私钥了。
最后一个url,是生成JWT的链接:https://appleid.apple.com
三、前端跳转到apple登录授权页面。
这部分是由前端去完成的,拼接好链接调用apple的登录授权页面。这里我直接引用一下大佬帖子的内容。
client_id:获取的client_id,必传
redirect_uri: 设置的重定向url,当用户同意授权后,会发起一个该URL的post请求,开发者需要在后台设置相应接口去接收他,服务端通过apple传来的code参数去请求身份令牌,必传。
scope:权限范围,name或者email,或者两个都设。
state:表示客户端的当前状态,可以指定任意值,会原封不动地返回这个值,你可以通过它做些验证,防止一些攻击。
这里面只有client_id,redirect_uri,是必须的,其他如果不设会自动设置默认值。你可以使用官方提供的按钮,当然也可以不用,当你点击登录按钮后会实际会跳转到一下地址,你可以选择直接手动拼接跳转授权页地址。
https://appleid.apple.com/auth/authorize?client_id=[CLIENT_ID]&redirect_uri=[REDIRECT_URI]&response_type=[RESPONSE_TYPE]&scope=[SCOPES]&response_mode=[RESPONSE_MODE]&state=[STATE]
四、接收授权码code。
按照上面的方法拼接好链接,请求到链接那边,用户登录apple账号后,apple服务器将发起一个POST请求至当时设置的redirect_uri,同时附上一个授权码code,id_token用于刷新token,首次登录将只有code和state。
然后此时需要服务端提供一个接口来接受这些参数。这时我们就需要考虑一个问题了。
前端是否需要传递参数到后端。(注意)
例如,我的项目中需要将游戏的主键ID传到后端来进行操作,此时如果我们将接收apple服务器传递参数的接口和后续验证code和token的接口做为同一个接口,即拿到code就直接进行验证的话,那前端那边是跳转在apple的登录授权页,是无法向后端传递游戏ID的。
所以我们做的这个接口只是一个中转的接口,接收到apple传递的参数后需返回给前端,让前端拿到这些参数随带着前端那边需传递的参数一起来请求我们的验证接口。
当然,如果前端不需要传参数的话,就可以拿到code直接去验证了。
然后我们就来写一个中转的接口:(注意是POST请求方式)
@PostMapping("/token")
public void getToken(AppleIdentity appleIdentity, HttpServletResponse resp) throws IOException {
Cookie tokenCookie = new Cookie("ID_TOKEN", appleIdentity.getId_token());
tokenCookie.setMaxAge(100); // Cookie的存活时间(自定义)
tokenCookie.setDomain("example.com");
tokenCook