java实现苹果登录(通过token解析相关数据)

以下示例代码、token是由移动端获取传给后端,后端解析验证即可

package com.sanxin.customer.util;
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;
        }
    }
}

以下测main方法

package com.sanxin.customer.util;
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) {
        // 请求的JWT
        String identityToken = "eyJraWQiOiJmaDZCczhDIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoib3JnLmNvY29hcG9kcy5kZW1vLlNYU2Fhc0xvZ2luLUV4YW1wbGUiLCJleHAiOjE2ODI2NzA1MDQsImlhdCI6MTY4MjU4NDEwNCwic3ViIjoiMDAxMDgwLmVkODFkN2YwYzc0MjQ5YjU4NTZjNmQ4MmY4MDg1ODI0LjA4MjgiLCJjX2hhc2giOiI4NXBTVGhtc0pQdmFjTlBrSHlHZWRBIiwiZW1haWwiOiJzeDEzMjg4ODg3NjA4QDE2My5jb20iLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJhdXRoX3RpbWUiOjE2ODI1ODQxMDQsIm5vbmNlX3N1cHBvcnRlZCI6dHJ1ZSwicmVhbF91c2VyX3N0YXR1cyI6Mn0.bqtZMM-CYIIQKDsNZMjUwRVx6tzSG3lkIerwFzbEDOOVnNXTD5Cz8Vh_GIrbspDwcCEDh1AsPpEwO_gkerYDDK7gY74RRywJr0iZANEUHNC7rpnMpw7IXDden2Hz6PTskHr5nYSd5ddUHCKr4JiltVGDJ7hJOzmpPmQKdq6zyItLGaaPlaTgPqoJoc9n1dGC4wtYX61tGw8TVL5Ozaa9fqxFnkSZBI6127zLOitncuU2HYEbO_ET_1HBQad0kaH6ytAvRjd1dDgv9UOSlqBHzQv2klgrRpiMr0Yqi3bX9YjBfhkppytLgee1vtpwxnGfH1NIvQ4d1JQBeVNER2PVeQ";
        // 解码后的消息体
        JSONObject playloadObj = IOSToeknUtils.parserIdentityToken(identityToken);
        System.out.println(playloadObj);
        Boolean success;
        try {
            success = IOSToeknUtils.verifyExc(identityToken, playloadObj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!success) {
            // TODO 校验token失败具体操作
            return;
        }
        // TODO 检验token成功具体业务操作。。。
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值