Windows系统 Apple 注销账户 Revoke Token

1 篇文章 0 订阅

收到Apple的邮件,所有的APP在6月30前要支持删除账号的功能。如果用Apple ID登录了APP,那么在注销账号的同时还需要解除Apple ID的授权,也就是Apple说的Revoke Token。这样Apple也知道这个账号已经被注销了,防止自动登录造成的安全问题.

写这篇文的主要原因是因为我用的是windows10系统,网上可参考的文献大多数都是苹果电脑,为了避免大家碰到相同的问题少走弯路,我把整个流程和要注意的点都写了出来

1.生成p8文件

Apple developer里面按下面的步骤生成一个p8文件

  • 1、进入 Certificates, Identifiers & Profiles > Keys,然后单击 Keys 旁边左上角的 + 号。
  • 2、提供密钥名称并确保勾选 Sign In with Apple。在这里,我们还必须单击 Configure。在接下来出现的 Configure Key 面板中,选择我们之前在 Choose a Primary App ID 下使用的 App ID,然后单击保存
  • 3、单击 Continue,然后在下一页中验证详细信息并单击 Register
  • 4、下载密钥并将其保存在安全的地方,因为您永远无法再次下载密钥。下载密钥后单击 Done

2.Ruby 安装 - Windows

 下载地址: Downloads    根据自己的电脑选取版本,我选的是最新版x64,直接安装就好了,这部分没有难点,安装过程会稍微有一点久,安装完成后查看一下版本 ,如果显示版本号说明安装成功了

命令: ruby -v

安装完成后加载jwt ,之后编译.rb文件时会用到

命令: gem install jwt

在桌面新建一个文本文档,把下列代码粘贴进去

require "jwt"
key_file = "xxxxx.p8"   #从Developer Center后台下载的key(p8后缀的文件)
team_id = "xxxxxx"      #开发者账号的teamID
client_id = "com.xxx.xxx"     #应用的BundleID
key_id = "xxxxxx"      #从Developer Center后台key_id
validity_period = 180  #有效期

private_key = OpenSSL::PKey::EC.new IO.read key_file

token = JWT.encode(
  {
    iss: team_id,
    iat: Time.now.to_i,
    exp: Time.now.to_i + 86400 * validity_period,
    aud: "https://appleid.apple.com",
    sub: client_id
  },
  private_key,
  "ES256",
  header_fields=
  {
    kid: key_id 
  }
)
puts token

填写对应的信息后,将文件后缀改为.rb格式,通过cmd运行.rb文件

在这里我运行时一直报错,改了几次还是不行,后来搜索了一下才明白,是文件夹的问题

把文件加改到C目录根目录下后,就可以了,这样我们就有了client_secret 

获取token的API接口:Generate and Validate Tokens

获取revoke的API接口:Revoke Tokens

调用逻辑 先获取token 会返回 access_token 和refresh_token 我测试了一下,只要类型对应两种都可以,分别对应访问令牌无效和刷新令牌无效,我用的是access_token,通过access_token调用revoke如果返回200就成功了.

这部分注意在调用revoke请求时 要设置

httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");

 下面是java部分代码,供大家参考

逻辑代码

    @PostMapping("/appleRevoke")
    @ResponseBody
    public ResultVo appleRevoke(@RequestBody Map<String, String> paramMap) {
        String tokenUrl = "https://appleid.apple.com/auth/token";
        Map<String, String> tokenUrlParam = new HashMap<>();
        tokenUrlParam.put("client_id", client_id);// 应用的BundleID
        tokenUrlParam.put("client_secret", client_secret);//通过.rb文件返回
        tokenUrlParam.put("code", paramMap.get("code"));//authorizationCode前端返回
        tokenUrlParam.put("grant_type", "authorization_code");//固定字符
        JSONObject tokenJsonObject = JSON.parseObject(HttpClientUtils.doPost(tokenUrl, tokenUrlParam, null));
        String apple_token =  tokenJsonObject.getString("access_token");
        if(apple_token==null){
            return new ResultVo(ResultVo.Status.OK,"apple_token获取失败");
        }
        String revokeUrl = "https://appleid.apple.com/auth/revoke";
        Map<String, String> revokeParam = new HashMap<>();
        revokeParam.put("client_id", client_id);
        revokeParam.put("client_secret", client_secret);
        revokeParam.put("token", apple_token);//tokenJsonObject 返回的 access_token
        revokeParam.put("token_type_hint", "access_token");//固定字符
        JSONObject revokeJsonObject = JSON.parseObject(HttpClientUtils.doPost(revokeUrl, revokeParam));
        if(revokeJsonObject.getString("code").equals("200")){
            return new ResultVo(ResultVo.Status.OK,"撤销令牌完成");
        }
        return new ResultVo(ResultVo.Status.OK,"撤销令牌失败");
    }

 http请求代码

import org.apache.http.client.methods.HttpPost;   
@Slf4j
public class HttpClientUtils {
 public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"UTF-8");
                Integer timeout = DEFALUT_TIMEOUT ;
                RequestConfig requestConfig = RequestConfig.custom()
                        .setConnectTimeout(timeout).setSocketTimeout(timeout).build();
                httpPost.setConfig(requestConfig);
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            } else {
                resultString=null;
            }
        } catch (Exception e) {
            log.error("HttpClient  doPost异常0"+e.getMessage(),e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPost(String url, Map<String, String> param,Integer timeout) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"UTF-8");
                timeout = (timeout == null ? DEFALUT_TIMEOUT : timeout);
                RequestConfig requestConfig = RequestConfig.custom()
                        .setConnectTimeout(timeout).setSocketTimeout(timeout).build();
                httpPost.setConfig(requestConfig);
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            log.error("HttpClient  doPost异常1"+e.getMessage(),e);
        } finally {
            try {
                if(response!=null){
                    response.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }
}

如果觉得有用,点个赞会让我觉得写这东西真的有人看.

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值