苹果登录和谷歌登录

直接贴代码,其实就只是需要封装两个工具类,直接用就没问题了

     

Controller中loginApple方法
    @PostMapping("/login")
    public Response loginApple(@RequestBody AppleLoginDTO dto){
        String appleUserId;
        String email;
        switch (dto.getSigninMethod()){
            case GOOGLE:
                GoogleAuthResult googleResult = GoogleAuthVerifier.verify(dto.getIdentityToken());
                appleUserId = googleResult.getSub();
                email = googleResult.getEmail();
                break;
            case APPLEID:
                AppleAuthResult verify = AppleAuthVerifier.verify(dto.getIdentityToken(), dto.getBundleId());
                appleUserId = verify.getSub();
                email = verify.getEmail();
                break;
            default:
                return null;
        }
        User user = userLoginService.findByAppleSub(appleUserId);
        if(user == null){
            user = userLoginService.createUser(appleUserId,email);
        }
        UserLoginVO result = new UserLoginVO(SignType.SIGNIN);
        result.setUser(user);
        result.setToken(UserTokenUtils.create(
                new UserToken(user.getId())
        ));
        return SingleResponse.ok(result);
    }
AppleLoginDTO
@Data
public class AppleLoginDTO {
    private String identityToken;
    private String bundleId;
    private SigninMethod signinMethod;
}
GoogleAuthVerifier
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class GoogleAuthVerifier {
    private static final String GOOGLE_AUTH_URL = "https://oauth2.googleapis.com/tokeninfo";

    public static GoogleAuthResult verify(String accessToken) {
        GoogleAuthResult result = null;
        HttpUrl url = HttpUrl.parse(GOOGLE_AUTH_URL).newBuilder()//
            .addQueryParameter("id_token", accessToken)//
            .build();
        final Request request = new Request.Builder() //
            .url(url) //
            .get() //
            .build(); //
        OkHttpClient okHttpClient = new OkHttpClient();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            result = GsonUtils.fromJson(response.body().string(), GoogleAuthResult.class);
        } catch (Exception e) {
            throw new SvcException(e.getMessage());
        }
        return result;
    }
}
AppleAuthVerifier
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class AppleAuthVerifier {
    private static final String APPLE_AUTH_KEYS_URL = "https://appleid.apple.com/auth/keys";
    private static final String ISSUER = "https://appleid.apple.com";
    private static Map<String, AppleAuthKey> appleKeyMap;

    /**
     * 获取苹果验证秘钥
     * 
     * @return
     */
    private static Map<String, AppleAuthKey> getAppleKeys() {
        if (MapUtils.isEmpty(appleKeyMap)) {
            Request request = new Request.Builder()//
                .url(APPLE_AUTH_KEYS_URL) //
                .get() //
                .build();
            OkHttpClient okHttpClient = new OkHttpClient();
            Call call = okHttpClient.newCall(request);
            try {
                Response response = call.execute();
                Type type = new TypeToken<Map<String, Object>>() {}.getType();
                Map<String, Object> keysMap = GsonUtils.fromJson(response.body().string(), type);
                type = new TypeToken<List<AppleAuthKey>>() {}.getType();
                List<AppleAuthKey> appleKeyList = GsonUtils.fromJson(GsonUtils.toJson(keysMap.get("keys")), type);
                appleKeyMap = appleKeyList.stream().collect(Collectors.toMap(AppleAuthKey::getKid, v -> v));
            } catch (IOException e) {
                throw new AppleAuthFailedException(e.getMessage());
            }
        }
        return appleKeyMap;
    }

    /**
     * 获取公钥
     * 
     * @param kid
     * @return
     */
    private static RSAPublicKey getPublicKey(String kid) {
        try {
            AppleAuthKey appleKey = getAppleKeys().get(kid);
            BigInteger modulus = new BigInteger(1, Base64.getUrlDecoder().decode(appleKey.getN()));
            BigInteger publicExponent = new BigInteger(1, Base64.getDecoder().decode(appleKey.getE()));

            RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
            KeyFactory kf = KeyFactory.getInstance(appleKey.getKty());// 目前kty均为 "RSA"
            return (RSAPublicKey)kf.generatePublic(spec);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            log.error("Decode publicKey failed: {}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 解码token
     * 
     * @param identityToken
     * @return
     */
    private static AppleAuthTokenHeader decodeTokenHeader(String identityToken) {
        String[] arr = identityToken.split("\\.");
        String deHeader = new String(Base64.getDecoder().decode(arr[0]));
        return GsonUtils.fromJson(deHeader, AppleAuthTokenHeader.class);
    }

    public static AppleAuthResult verify(String identityToken, String bundleId) {
        AppleAuthTokenHeader header = decodeTokenHeader(identityToken);
        Algorithm algorithm = Algorithm.RSA256(getPublicKey(header.getKid()), null);
        JWTVerifier verifier = JWT.require(algorithm)//
            .withIssuer(ISSUER) //
            .withAudience(bundleId) //
            .build();
        DecodedJWT decodedJWT = verifier.verify(identityToken);
        final Map<String, Object> maps = Maps.newHashMap();
        decodedJWT.getClaims().entrySet().forEach(item -> maps.put(item.getKey(), item.getValue().as(Object.class)));
        return GsonUtils.fromJson(GsonUtils.toJson(maps), AppleAuthResult.class);
    }
}

直接拿着用就没问题了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值