Sign in with Apple(苹果授权登陆)服务端验证-测试通过版

Sign in with Apple(苹果授权登陆)服务端验证-测试通过版

            • 1.先引用2个jwt用到的jar包
            • 2.算法的工具类
            • 三方登录调用验证工具类

苹果登录方式有2种,这里介绍基于JWT算法验证
废话不多说,上代码

1.先引用2个jwt用到的jar包
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>jwks-rsa</artifactId>
            <version>0.9.0</version>
        </dependency>
2.算法的工具类
package com.imc.common;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwk.Jwk;
import io.jsonwebtoken.*;
import org.apache.commons.codec.binary.Base64;

import java.security.PublicKey;
import java.util.HashMap;

/**
 * 
* date:2012/03/26 9:43 * * @author xh * @version 1.0 * @since JDK 1.8 */
public class SignInWithAppleHelper { /** * 解密个人信息 * * @param identityToken APP获取的identityToken * @return 解密参数:失败返回null */ public String verify(String identityToken) { try { if (identityToken.split("\\.").length > 1) { String claim = new String(Base64.decodeBase64(identityToken.split("\\.")[1])); String aud = JSONObject.parseObject(claim).get("aud").toString(); String sub = JSONObject.parseObject(claim).get("sub").toString(); String reuslt = this.verify(this.getPublicKey(), identityToken, aud, sub); if (reuslt.equals("SUCCESS")) { System.out.println("苹果登录成功"); return claim; } } } catch (Exception e) { e.printStackTrace(); } return null; } public static String verify(PublicKey key, String jwt, String audience, String subject) throws Exception { String result = "FAIL"; JwtParser jwtParser = Jwts.parser().setSigningKey(key); 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")) { result = "SUCCESS"; return result; } } catch (ExpiredJwtException e) { throw new Exception("苹果token过期", e); } catch (SignatureException e) { throw new Exception("苹果token非法", e); } return result; } /** * 从hex string生成公钥 * * @return 构造好的公钥 */ public PublicKey getPublicKey() { try { String str = HttpHelper.get("https://appleid.apple.com/auth/keys", new HashMap<String, String>()); JSONObject data = JSONObject.parseObject(str); String keys = data.getString("keys"); JSONArray arr = JSONObject.parseArray(keys); JSONObject jsonObject1 = JSONObject.parseObject(arr.getString(0)); Jwk jwa = Jwk.fromValues(jsonObject1); PublicKey publicKey = jwa.getPublicKey(); return publicKey; } catch (final Exception e) { e.printStackTrace(); } return null; } }
三方登录调用验证工具类

仔细看,很多文档都没有的东西来了,我这块用到了缓存,为什么用缓存呢,因为这块代码在我反复测试的情况下,移动端给的identityToken参数你频繁操作的话jwt验证会报错,在本楼主大量实验的情况下测试出 一个userID 对应的identityToken有效期是10分钟,userID是苹果给用户的唯一标识,所以我把userID当做key ,把identityToken存到redis内,我这里缓存是9分钟,我是考虑到网络IO等,反正不差那1分钟,经测试没问题,产品逻辑可适当修改

 if (type == Constants.LOGIN_TYPE_APPLE) {
     
            //苹果登陆使用参数
            String identityToken = params.getString("identityToken");
            //苹果登录唯一表示
            thirdLoginId = params.getString("userID");
            if (redisCacheUtil.get(thirdLoginId) != null) {
     
                identityToken = redisCacheUtil.get(thirdLoginId) + "";
            }
            //这里可以根据thirdLoginId查询数据库是否存在,如果存在就返回用户信息
            //苹果登陆验证
            SignInWithAppleHelper signInWithAppleHelper = new SignInWithAppleHelper();
            String data = signInWithAppleHelper.verify(identityToken);
            if (data != null) {
     
                //苹果登录唯一表示
                thirdLoginId = JSONObject.parseObject(data).get("sub").toString();
                if (redisCacheUtil.get(thirdLoginId) == null) {
     
                    redisCacheUtil.set(thirdLoginId, identityToken, 540);
                }
            } else {
     
                throw new CustomException(code_3010, "与苹果服务器链接超时,请重新尝试。");
            }
        }

不喜勿喷,感谢各位大大的阅读

你可能感兴趣的:(编码生活,java,redis)