苹果联合登录

2020-03-09  本文已影响0人  大强斌

不知道为啥苹果提供的联合登录竟然连demo都没有,你有个小例子也好啊。参阅了很多前辈的文章,怀着坎坷的心情,猜,懵,最终调试ok并跑起来。直接贴代码。大半夜写的文章,希望你们喜欢,喜欢的话点个赞。

说下实现的过程:

  A密钥的生成 参考https://www.jianshu.com/p/cbcb79067451,不知道为什么我机器死活不行,别人按照相同的步骤就可以。

B 苹果业务流程,方案一,和方案二,可以分别使用来获取到苹果的openid,

       方案一code 获取token

                 前端往后端传递useriid就是苹果的的用户openid,你只需要检验token是否合法就可以。

       方案二 获取公钥去解析返回的token,这是解析jwt的方式。前期正常,后期发现,多次请求只有一次成功,不知道苹果服务器官方做出了什么变化。特此说明下。你也可以试试。代码参考下面的。

        参考截图

具体代码 

package com.secoo.user.oauth.impl;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import com.auth0.jwk.InvalidPublicKeyException;

import com.auth0.jwk.Jwk;

import com.secoo.user.bean.OAuthTokenInfo;

import com.secoo.user.bean.OAuthUserInfo;

import com.secoo.user.bean.Result;

import com.secoo.user.config.AppDiabloConfig;

import com.secoo.user.dto.OAuthRequestDto;

import com.secoo.user.oauth.AppletIOAuth2Service;

import com.secoo.user.util.HttpUtil;

import io.jsonwebtoken.*;

import org.apache.commons.lang.StringUtils;

import org.apache.http.HttpResponse;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;

import java.security.PublicKey;

import java.util.Base64;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

@Component("appleService")

public class AppletOAuth2ServiceImplimplements AppletIOAuth2Service {

public static  StringtokenUrl ="https://appleid.apple.com/auth/token";

public static  StringpublicUrl ="https://appleid.apple.com/auth/keys";

private static Loggerlogger = LoggerFactory.getLogger(AppletOAuth2ServiceImpl.class);

@Autowired

    AppDiabloConfigappDiabloConfig;

/**

* 苹果请求验证token

*

    * @param map

    * @return

    */

    @Override

    public String postAppleToken(Map map) {

Map form =new HashMap();

form.put("client_id",appDiabloConfig.getAppletClientId());//从配置文件获取

        form.put("client_secret",appDiabloConfig.getAppletClientIdSecret());//从配置文件获取

        form.put("grant_type","authorization_code");

form.put("code", (String)map.get("code"));

String appResult="";

try {

appResult= HttpUtil.doPost(tokenUrl, form);

//  HttpResponse result = client.excutePost(tokenUrl, form);

        }catch (Exception e) {

logger.error("applet token request faild:"+map.get("ccode"), e.getMessage());

}

return  appResult;

}

/**

* 苹果请求公钥

*

    * @return

    */

    @Override

    public PublicKey getPublic(String code) {

String appResult="";

PublicKey publicKey=null;

try {

appResult= HttpUtil.doGet(publicUrl,"utf-8",2000);

}catch (Exception e) {

logger.error("applet public sec request faild", e.getMessage());

}

if(StringUtils.isNotEmpty(appResult)) {

Map maps = (Map) JSON.parse(appResult);

List keys = (List) maps.get("keys");

Map o = (Map) keys.get(0);

Jwk jwa = Jwk.fromValues(o);

try {

publicKey = jwa.getPublicKey();

}catch (InvalidPublicKeyException e) {

logger.error("applet public sec request faild code:"+code, e.getMessage());

}

}

return  publicKey;

}

/**

* 解析token,返回的结果

*

    * @param jwtString

    * @return

    */

    @Override

    public Map verifyTokenJWT(String jwtString,PublicKey key,String code) {

//获取主体

        Map map=getSubByJwt(jwtString);

if(map==null){

logger.info("getSubByJwt is null code:"+code);

return null;

}

Map back=null;

final JwtParser jwtParser = Jwts.parser().setSigningKey(key);

jwtParser.requireIssuer("https://appleid.apple.com");

jwtParser.requireAudience((String) map.get("aud"));

jwtParser.requireSubject((String)map.get("sub"));

try {

final Jws claim = jwtParser.parseClaimsJws(jwtString);

logger.info("verifyTokenJWT code:"+code+" result:"+(claim==null?"null":JSON.toJSONString(claim)));

if (claim !=null && claim.getBody().containsKey("sub")) {

back=new HashMap();

back.put("sub", claim.getBody().get("sub"));

}

}catch (final ExpiredJwtException e) {

logger.warn("apple decry jwt error code:"+code,e);

}catch (final Exception e) {

logger.warn("apple decry jwt error code:"+code,e);

}

return back;

}

/**

* 通过jwt获取主体和签名

    * @param jwtString

    * @return

    */

    public Map getSubByJwt(String jwtString) {

String jwt = jwtString;

String payload = jwt.split("\\.")[1];

String sub ="";

String aud ="";

Map result =null;

final Base64.Decoder decoder = Base64.getDecoder();

final Base64.Encoder encoder = Base64.getEncoder();

String decode =null;

try {

decode =new String(decoder.decode(jwt.split("\\.")[1]),"UTF-8");

String substring = decode.substring(0, decode.indexOf("}") +1);

JSONObject jsonObject = JSON.parseObject(substring);

sub = jsonObject.getString("sub");

aud = jsonObject.getString("aud");

if (StringUtils.isNotEmpty(sub) && StringUtils.isNotEmpty(aud)) {

result =new HashMap();

result.put("sub", sub);

result.put("aud", aud);

}

}catch (UnsupportedEncodingException e) {

logger.info("getSubByJwt faild", e.getMessage());

}

return result;

}

/**

* 第三方标识

*/

    @Override

    public Integer getSourceId() {

return 11;

}

/**

* 获取第三方AccessToken信息

*

    * @param reqTokenDto

    * @return

    */

    @Override

    public Result getAccessTokenInfo(OAuthRequestDto reqTokenDto) {

return null;

}

/**

* 通过accessToken获取第三方用户信息

*

    * @param tokenInfo

    * @return

    */

    @Override

    public Result getUserInfo(OAuthTokenInfo tokenInfo) {

return null;

}

/**

* 获取第三方用户信息

*

    * @param reqTokenDto

    * @return

    */

    @Override

    public Result getUserInfo(OAuthRequestDto reqTokenDto) {

return null;

}

/**

* 获取缓存中第三方用户信息

*

    * @param reqTokenDto

    * @return

    */

    @Override

    public Result getCacheUserInfo(OAuthRequestDto reqTokenDto) {

return null;

}

/**

* 删除缓存中第三方用户信息

*

    * @param reqTokenDto

    * @return

    */

    @Override

    public void delCacheUserInfo(OAuthRequestDto reqTokenDto) {

}

}

pom文件

<dependency>

<groupId>io.jsonwebtoken</groupId>

<artifactId>jjwt</artifactId>

<version>0.7.0</version>

</dependency>

<dependency>

<groupId>com.auth0</groupId>

<artifactId>jwks-rsa</artifactId>

<version>0.9.0</version>

</dependency>

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpcore-nio</artifactId>

<version>4.4.5</version>

</dependency>

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpasyncclient</artifactId>

<version>4.1.2</version>

</dependency>

欢迎大家联系我,主要关注中间件底层的设计和实现,生活资讯,大家一起分享。

上一篇 下一篇

猜你喜欢

热点阅读