token是客户端完成google登陆时传到后端的jwt
clientId 类似
2xxxxxxxxx2-a61mqdtnkhsxxxxxxxxxx5ca6l9.apps.googleusercontent.com
使用的maven
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.24.1</version>
<scope>compile</scope>
</dependency>
public static Boolean googleJwtVerification(String token, String clientId) {
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
new NetHttpTransport(), JacksonFactory.getDefaultInstance())
.setAudience(Collections.singletonList(clientId)).build();
GoogleIdToken idToken = null;
try {
idToken = verifier.verify(token);
log.info("google验证解析出来的结果{}", idToken.getPayload());
return true;
} catch (GeneralSecurityException e) {
log.info("验证时出现GeneralSecurityException异常");
} catch (IOException e) {
System.out.println("验证时出现IOException异常");
}
return false;
}
需要先请求获取facebook的jwts json数据,然后转成RSAPublicKey,然后使用公钥对jwt进行验证
这里还可以加一步进行判断对clientId的验证
注意:正常facebook是不进行这一步的,因为ios同事看错了文档
因为接的下面一个,所以就会传入一个jwt过来,如果不校验的话,别人可以串改jwt然后可以生成n个新用户 。
如果是接上面那个,是可以调用接口去获取facebook用户信息的
facebook jwt文档解释https://developers.facebook.com/docs/facebook-login/limited-login/token/validating
maven
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.15.0</version>
</dependency>
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>0.6.4</version>
</dependency>
private static List<RSAPublicKey> faceBookPublicKeys = new ArrayList<>();
private static String faceBooKJwksUrl = "https://www.facebook.com/.well-known/oauth/openid/jwks/";
public static Boolean faceBookJwtVerification(String token) {
if (CollectionUtil.isEmpty(faceBookPublicKeys)) {
init();
}
for (RSAPublicKey faceBookPublicKey : faceBookPublicKeys) {
//根据密钥对生成RS256算法对象
Algorithm algorithm = Algorithm.RSA256(faceBookPublicKey);
log.info("PublicKey: " + faceBookPublicKey.getPublicExponent());
//解密时,使用gong钥生成算法对象
JWTVerifier verifier = JWT.require(algorithm)
.build();
try {
//验证Token,verifier自动验证
DecodedJWT jwt = verifier.verify(token);
log.info("验证解析出来的facebook信息:{}", jwt.getPayload());
return true;
} catch (JWTVerificationException e) {
log.error("Token无法通过验证! " + e.getMessage());
return false;
}
}
return false;
}
private static void init() {
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
if (CollectionUtil.isNotEmpty(faceBookPublicKeys)) {
return;
}
log.info("查询facebook公钥开始");
String responseResult = HttpRequest.get(faceBooKJwksUrl).setConnectionTimeout(3000).timeout(3000).execute().body();
if (StrUtil.isNotBlank(responseResult)) {
JSONObject jsonObject = JSONObject.parseObject(responseResult);
JSONArray keys = jsonObject.getJSONArray("keys");
for (int i = 0; i < keys.size(); i++) {
JSONObject key = keys.getJSONObject(i);
RsaJsonWebKey pub = null;
try {
pub = new RsaJsonWebKey(key);
} catch (JoseException e) {
e.printStackTrace();
}
//获取公钥
RSAPublicKey rsaPublicKey = pub.getRsaPublicKey();
faceBookPublicKeys.add(rsaPublicKey);
}
}
log.info("查询facebook公钥结束");
} finally {
lock.unlock();
}
}
apple
和facebook的流程差不多,就是获取到的公钥不一样,转换成RSAPublicKey 的方法也不一样
private static String appleJwksUrl = "https://appleid.apple.com/auth/keys";
private static String appleJwksCache = "{\"keys\":[{\"kty\":\"RSA\",\"kid\":\"YuyXoY\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"1JiU4l3YCeT4o0gVmxGTEK1IXR-Ghdg5Bzka12tzmtdCxU00ChH66aV-4HRBjF1t95IsaeHeDFRgmF0lJbTDTqa6_VZo2hc0zTiUAsGLacN6slePvDcR1IMucQGtPP5tGhIbU-HKabsKOFdD4VQ5PCXifjpN9R-1qOR571BxCAl4u1kUUIePAAJcBcqGRFSI_I1j_jbN3gflK_8ZNmgnPrXA0kZXzj1I7ZHgekGbZoxmDrzYm2zmja1MsE5A_JX7itBYnlR41LOtvLRCNtw7K3EFlbfB6hkPL-Swk5XNGbWZdTROmaTNzJhV-lWT0gGm6V1qWAK2qOZoIDa_3Ud0Gw\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"kid\":\"W6WcOKB\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"2Zc5d0-zkZ5AKmtYTvxHc3vRc41YfbklflxG9SWsg5qXUxvfgpktGAcxXLFAd9Uglzow9ezvmTGce5d3DhAYKwHAEPT9hbaMDj7DfmEwuNO8UahfnBkBXsCoUaL3QITF5_DAPsZroTqs7tkQQZ7qPkQXCSu2aosgOJmaoKQgwcOdjD0D49ne2B_dkxBcNCcJT9pTSWJ8NfGycjWAQsvC8CGstH8oKwhC5raDcc2IGXMOQC7Qr75d6J5Q24CePHj_JD7zjbwYy9KNH8wyr829eO_G4OEUW50FAN6HKtvjhJIguMl_1BLZ93z2KJyxExiNTZBUBQbbgCNBfzTv7JrxMw\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"kid\":\"fh6Bs8C\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"u704gotMSZc6CSSVNCZ1d0S9dZKwO2BVzfdTKYz8wSNm7R_KIufOQf3ru7Pph1FjW6gQ8zgvhnv4IebkGWsZJlodduTC7c0sRb5PZpEyM6PtO8FPHowaracJJsK1f6_rSLstLdWbSDXeSq7vBvDu3Q31RaoV_0YlEzQwPsbCvD45oVy5Vo5oBePUm4cqi6T3cZ-10gr9QJCVwvx7KiQsttp0kUkHM94PlxbG_HAWlEZjvAlxfEDc-_xZQwC6fVjfazs3j1b2DZWsGmBRdx1snO75nM7hpyRRQB4jVejW9TuZDtPtsNadXTr9I5NjxPdIYMORj9XKEh44Z73yfv0gtw\",\"e\":\"AQAB\"}]}";
public static Boolean appleJwtVerification(String token) {
List<JSONObject> arr = getAuthKeys();
if (arr == null) {
return false;
}
//先取jwt中的header来匹配苹果公钥的kid
java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
String header = new String(decoder.decode(token.split("\\.")[0]));
JSONObject headJsonObject = JSONObject.parseObject(header);
for (JSONObject jsonObject : arr) {
String headKid = headJsonObject.getString("kid");
String headAlg = headJsonObject.getString("alg");
String kid = jsonObject.getString("kid");
String alg = jsonObject.getString("alg");
if (headKid.equals(kid) && headAlg.equals(alg)) {
// 验证
try {
RsaJsonWebKey rsaJsonWebKey = new RsaJsonWebKey(jsonObject);
//获取公钥
RSAPublicKey rsaPublicKey = rsaJsonWebKey.getRsaPublicKey();
//根据密钥对生成RS256算法对象
Algorithm algorithm = Algorithm.RSA256(rsaPublicKey);
log.info("PublicKey: " + rsaPublicKey.getPublicExponent());
//解密时,使用gong钥生成算法对象
JWTVerifier verifier = JWT.require(algorithm)
.build();
//验证Token,verifier自动验证
DecodedJWT jwt = verifier.verify(token);
log.info("验证解析出来的apple信息:{}", jwt.getPayload());
return true;
} catch (JWTVerificationException e) {
log.error("Token无法通过验证! " + e.getMessage());
return false;
} catch (JoseException e) {
log.error("Token无法通过验证! " + e.getMessage());
return false;
}
}
}
return false;
}
private static List<JSONObject> getAuthKeys() {
List<JSONObject> publicKeys = new ArrayList<>();
try {
String responseResult = HttpRequest.get(appleJwksUrl).setConnectionTimeout(3000).timeout(3000).execute().body();
if (StrUtil.isNotBlank(responseResult)) {
JSONObject jsonObject = JSONObject.parseObject(responseResult);
JSONArray keys = jsonObject.getJSONArray("keys");
for (int i = 0; i < keys.size(); i++) {
JSONObject jsonObject1 = keys.getJSONObject(i);
publicKeys.add(jsonObject1);
}
}
log.info("苹果公钥" + responseResult);
} catch (Exception e) {
log.info("AppleLogin获取公钥发生错误,先用本地的公钥" + e);
JSONObject jsonObject = JSONObject.parseObject(appleJwksCache);
JSONArray keys = jsonObject.getJSONArray("keys");
for (int i = 0; i < keys.size(); i++) {
JSONObject jsonObject1 = keys.getJSONObject(i);
publicKeys.add(jsonObject1);
}
}
return publicKeys;
}