public class IosAppIdLoginServiceImp { private static final Logger LOGGER = LoggerFactory.getLogger(IosAppIdLoginServiceImpl.class); @Autowired private PropertiesResouseUtil propertiesResouseUtil; private static final String AUTH_TIME = "auth_time"; private final static int READ_TIMEOUT = 100; private final static int CONNECT_TIMEOUT = 60; @Override public Response<T> verifyIdentityToken(Request<IosAppIdLoginDto> request) { Response<T> response = new Response<>(); IosAppIdLoginDto iosAppIdLoginDto = request.getRequestParam(); response.setResult(iosAppIdLoginDto); try { //解析 Map<String, JSONObject> json = parserIdentityToken(iosAppIdLoginDto.getIdentityToken()); JSONObject header = json.get("header"); String kid = header.getString("kid"); //生成publickey PublicKey publicKey = getPublicKey(kid); if (publicKey == null) { iosAppIdLoginDto.setSuccess(false); LOGGER.info("获取苹果验证公钥失败:kid={}",kid); return commonResponse; } JSONObject payload = json.get("payload"); //验证 JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey); jwtParser.requireIssuer(propertiesResouseUtil.getProperty("apple.url"));//+"/auth/keys" jwtParser.requireAudience(payload.getString("aud")); jwtParser.requireSubject(payload.getString("sub")); Jws<Claims> claim = jwtParser.parseClaimsJws(iosAppIdLoginDto.getIdentityToken()); if (claim != null && claim.getBody().containsKey(AUTH_TIME)) { // String sub = claim.getBody().get("sub").toString();//用户的Apple的openId // String iss = claim.getBody().get("iss").toString(); // String aud = claim.getBody().get("aud").toString(); iosAppIdLoginDto.setSuccess(true); } } catch (ExpiredJwtException e1) { iosAppIdLoginDto.setSuccess(false); LOGGER.error("apple token verify fail,identityToken is expired!",e1); } catch (Exception e2) { iosAppIdLoginDto.setSuccess(false); LOGGER.error("apple token verify fail,error={}", e2); } return commonResponse; } /** * 对前端传来的JWT字符串identityToken的第二部分进行解码 * 主要获取其中的aud和sub,aud对应ios前端的包名,sub对应当前用户的授权openID * * @param identityToken * @return */ private Map<String, JSONObject> parserIdentityToken(String identityToken) { Map<String, JSONObject> map = new HashMap<String, JSONObject>(); String[] arr = identityToken.split("\\."); String deHeader = new String(Base64.decodeBase64(arr[0])); JSONObject header = JSON.parseObject(deHeader); LOGGER.info("获取的header={}",header); map.put("header", header); String dePayload = new String(Base64.decodeBase64(arr[1])); LOGGER.info("获取dePayload={}",header); JSONObject payload = JSON.parseObject(dePayload); map.put("payload", payload); return map; } /** * 获取publickey * @param kid * @return */ private PublicKey getPublicKey(String kid) { LOGGER.info("get apple public key start,kid={}", kid); try { Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(propertiesResouseUtil.getProperty("httpproxy.url"), Integer.parseInt(propertiesResouseUtil.getProperty("httpproxy.port")))); OkHttpClient client = new OkHttpClient().newBuilder().proxy(proxy).connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).build(); Request request = new Request.Builder().url(propertiesResouseUtil.getProperty("apple.url")+"/auth/keys").build(); Response response = client.newCall(request).execute(); if(response.isSuccessful()){ // 得到响应体中的身体,将其转成 string String string = response.body().string(); JSONObject data = JSONObject.parseObject(string); JSONArray jsonArray = data.getJSONArray("keys"); if(jsonArray.isEmpty()) { return null; } for (Object object : jsonArray) { JSONObject json = ((JSONObject)object); if(json.getString("kid").equals(kid)) { json = ((JSONObject)object); Jwk jwa = Jwk.fromValues(json); return jwa.getPublicKey(); } } } } catch (final Exception e) { LOGGER.error("apple getPublicKey error", e); } return null; } } pom.xml 引用包
<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>
相关推荐
SDK 提供了多种接口,包括显式登录接口、隐式登录接口、OAuth 登录接口、注销用户账号接口、获取用户信息接口、查询用户状态接口、验证本机号码等。 5. SDK 错误码说明 SDK 提供了错误码详述,帮助开发者快速解决...
在实现QQ一键登录的过程中,首先需要在腾讯开放平台上注册应用,获取到AppID和AppKey,这两个参数是识别应用身份的关键。然后,在用户点击“QQ登录”按钮时,应用会跳转到腾讯的授权页面,用户在此页面确认授权后,...
**Ecmall一键登录功能与QQ OAuth2.0整合** 在电子商务领域,提供便捷的一键登录功能对于提升用户体验和增加用户粘性具有重要的作用。Ecmall是一款开源的电子商务平台,它提供了集成多种社交账号登录的功能,使得...
开发者可以通过申请获取AppID和AppKey,然后引导用户跳转到腾讯提供的授权页面,用户同意后,服务端会返回一个授权码,通过这个授权码可以换取访问令牌,进而获取用户的基本信息,实现登录功能。 对于新浪微博,...
在实现QQ一键登录时,我们需要在WebView中加载QQ提供的登录接口页面。 1. **配置WebView** - 在AndroidManifest.xml中添加INTERNET权限,以允许WebView访问网络。 ```xml ``` - 初始化WebView,设置...
易优QQ一键登录插件是方便会员进行快捷注册登录操作,为站长带来更多活跃会员 使用此插件要注意一下几点: 1、此插件使用前请到 https://connect.qq.com/ 申请appid, appkey, 并注册callback地址 2、配置完成...
要使用这个.NET版本的QQ一键登录库,首先你需要在QQ互联官网上进行开发者注册,创建应用并获取App ID(APPID)和App Key(APPKEY)。这两个参数是识别你的应用身份的关键,必须妥善保管,避免泄露。 在完成注册和...
1. **QQ开放平台**: QQ一键登录基于QQ开放平台(Tencent Open API),该平台为开发者提供了各种API接口,包括用户身份验证、社交信息获取等。开发者需要在QQ开放平台上注册并创建应用,获取AppID和AppKey,这两个...
《PBOOTCMS微信一键登录详解》 在当前的互联网环境中,用户登录体验的便捷性成为了网站吸引和留住用户的关键因素之一。PBOOTCMS作为一个轻量级的PHP内容管理系统,其强大的扩展性和灵活性使得开发者能够轻松实现...
在iOS应用开发中,集成第三方服务是常见的需求,如微信登录、Apple登录、内购功能、Google和Facebook的社交分享以及AppsFlyer的移动归因分析。这些功能为用户提供便利,同时也增强了应用的互动性和盈利能力。本文将...
在iOS应用开发中,短信验证是一种常见的用户身份验证机制,用于确保用户提供的手机号码真实有效。这个"iOS 短信验证demo"就是一个简单的实例,它演示了如何集成短信验证功能到iOS应用中。通常,这个过程涉及以下几个...
微信小程序开发一键登录 获取session_key和openid实例 思来想去不愿自己的微信小程序是个单机版本.自己又不会写后台.现在借助leancloud可以实现微信小程序一键登录功能.尝试后,做笔记. 第一步:下载av-weapp.js,放到...
中国移动的“和通行证”开发指南Android v1.3主要针对的是如何在Android平台上实现便捷的一键登录功能。这个服务允许用户通过一次身份验证就能轻松访问各种应用或服务,尤其适用于那些插有中国移动SIM卡的设备,它能...
Destoon QQ互联一键登录审核不通过的问题通常是由于网站设置不符合QQ互联的审核标准,导致用户在尝试使用QQ一键登录时出现错误,如无跳转、提示失败或出现错误信息。解决这个问题需要对网站的模板文件进行调整,以及...
在这个场景中,我们关注的是ECSHOP如何集成QQ一键登录功能,这通常涉及到OAuth 2.0授权协议。OAuth 2.0是互联网上广泛使用的授权框架,允许第三方应用在用户许可的情况下访问其存储在另一服务上的特定信息,而无需...
《中国移动一键登录开发指南Android v1.3》是针对Android平台的应用开发者提供的详细技术文档,旨在帮助开发者快速集成中国移动的“和通行证”服务,实现用户的一键登录功能。该服务利用中国移动的网络和SIM卡能力,...