2026/6/1 15:22:34
网站建设
项目流程
网站全站模板,前端刚毕业开多少工资,seo整站优化外包公司,腾讯云做网站步骤领券公众号 Oauth2.0 授权链路#xff1a;淘宝联盟三段式跳转 STATE 参数防重放设计
大家好#xff0c;我是 微赚淘客系统3.0 的研发者省赚客#xff01;
用户通过微信公众号点击“一键授权领券”后#xff0c;需完成 微信 → 自有服务 → 淘宝联盟 → 回调自有服务 → 跳…领券公众号 Oauth2.0 授权链路淘宝联盟三段式跳转 STATE 参数防重放设计大家好我是 微赚淘客系统3.0 的研发者省赚客用户通过微信公众号点击“一键授权领券”后需完成微信 → 自有服务 → 淘宝联盟 → 回调自有服务 → 跳回微信的三段式跳转。该流程依赖 OAuth2.0 的state参数传递上下文但若state可预测或可复用将导致CSRF 攻击或授权会话劫持。我们基于加密 Token Redis 一次性校验实现高安全防重放机制。一、三段式跳转流程用户在微信中点击链接https://wx.juwatech.cn/auth/start?item_id675849302后端生成唯一state重定向至淘宝联盟授权页淘宝联盟授权后回调redirect_uri?codexxxstateyyy后端用code换取access_token绑定用户与推广关系最终跳回微信 H5 页面展示优惠券。关键风险点攻击者截获state后可伪造回调绑定他人账号。二、STATE 参数结构设计state不再是简单 UUID而是包含时间戳 用户标识 随机盐 签名的加密字符串packagejuwatech.cn.oauth.state;publicclassAuthState{privatelongtimestamp;// 有效期控制5分钟privateStringopenId;// 微信 openid防跨用户privateStringitemId;// 商品ID防跨商品privateStringnonce;// 随机盐// getters setters}序列化后使用 AES 加密并 Base64 编码作为state值。三、STATE 生成与存储packagejuwatech.cn.oauth.service;ServicepublicclassOAuthStateService{privatestaticfinalStringSTATE_PREFIXoauth:state:;privatestaticfinallongEXPIRE_SECONDS300;// 5分钟publicStringgenerateState(StringopenId,StringitemId){AuthStatestateObjnewAuthState();stateObj.setTimestamp(System.currentTimeMillis());stateObj.setOpenId(openId);stateObj.setItemId(itemId);stateObj.setNonce(UUID.randomUUID().toString().replace(-,));// 序列化为 JSONStringjsonJsonUtils.toJson(state).replaceAll(\\s,);// AES 加密使用固定密钥StringencryptedAesUtils.encrypt(json,JUWATECH_OAUTH_KEY_2026);// 生成 Redis Key防止重复使用StringstateTokenDigestUtils.sha256Hex(encrypted);StringredisKeySTATE_PREFIXstateToken;// 存入 Redis仅用于标记已使用值不重要redisTemplate.opsForValue().set(redisKey,1,Duration.ofSeconds(EXPIRE_SECONDS));returnencrypted;// 直接返回加密串作为 state}}前端重定向示例GetMapping(/auth/start)publicvoidstartAuth(RequestParamStringitem_id,RequestParamStringopen_id,HttpServletResponseresponse)throwsIOException{StringstateoAuthStateService.generateState(open_id,item_id);StringtaobaoAuthUrlhttps://oauth.taobao.com/authorize?client_idYOUR_APP_KEYredirect_urihttps://api.juwatech.cn/oauth/callbackresponse_typecodestateURLEncoder.encode(state,StandardCharsets.UTF_8);response.sendRedirect(taobaoAuthUrl);}四、回调时 STATE 校验与防重放GetMapping(/oauth/callback)publicvoidhandleCallback(RequestParamStringcode,RequestParamStringstate,HttpServletResponseresponse)throwsIOException{try{// 1. 解密 stateStringjsonAesUtils.decrypt(state,JUWATECH_OAUTH_KEY_2026);AuthStateauthStateJsonUtils.parse(json,AuthState.class);// 2. 校验时效if(System.currentTimeMillis()-authState.getTimestamp()300_000){thrownewIllegalArgumentException(State expired);}// 3. 构造 Redis Key 并检查是否已使用StringstateTokenDigestUtils.sha256Hex(state);StringredisKeyoauth:state:stateToken;BooleanexistsredisTemplate.hasKey(redisKey);if(Boolean.FALSE.equals(exists)){thrownewSecurityException(Invalid or reused state);}// 4. 原子性删除防止重放BooleandeletedredisTemplate.delete(redisKey);if(Boolean.FALSE.equals(deleted)){thrownewSecurityException(State already consumed);}// 5. 用 code 换取 access_tokenTaobaoTokenResponsetokenResptaobaoClient.getAccessToken(code);// 6. 绑定推广关系openId 淘宝 sessionpromotionService.bindUser(authState.getOpenId(),tokenResp.getAccessToken(),authState.getItemId());// 7. 跳回微信成功页StringredirectUrlhttps://wx.juwatech.cn/coupon/success?item_idauthState.getItemId();response.sendRedirect(redirectUrl);}catch(Exceptione){log.warn(OAuth callback failed,e);response.sendRedirect(https://wx.juwatech.cn/error?msgauth_failed);}}五、AES 工具类实现CBC PKCS5Paddingpackagejuwatech.cn.common.crypto;publicclassAesUtils{publicstaticStringencrypt(StringplainText,Stringkey){try{byte[]keyBytesArrays.copyOf(key.getBytes(StandardCharsets.UTF_8),16);SecretKeySpeckeySpecnewSecretKeySpec(keyBytes,AES);CiphercipherCipher.getInstance(AES/CBC/PKCS5Padding);IvParameterSpecivnewIvParameterSpec(keyBytes);// 使用 key 前16字节作 IVcipher.init(Cipher.ENCRYPT_MODE,keySpec,iv);byte[]encryptedcipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));returnBase64.getEncoder().encodeToString(encrypted);}catch(Exceptione){thrownewRuntimeException(AES encrypt failed,e);}}publicstaticStringdecrypt(StringencryptedBase64,Stringkey){try{byte[]keyBytesArrays.copyOf(key.getBytes(StandardCharsets.UTF_8),16);SecretKeySpeckeySpecnewSecretKeySpec(keyBytes,AES);CiphercipherCipher.getInstance(AES/CBC/PKCS5Padding);IvParameterSpecivnewIvParameterSpec(keyBytes);cipher.init(Cipher.DECRYPT_MODE,keySpec,iv);byte[]decryptedcipher.doFinal(Base64.getDecoder().decode(encryptedBase64));returnnewString(decrypted,StandardCharsets.UTF_8);}catch(Exceptione){thrownewRuntimeException(AES decrypt failed,e);}}}六、安全增强措施密钥轮换每季度更新JUWATECH_OAUTH_KEY_2026旧密钥保留 7 天兼容IP 绑定可选在AuthState中加入客户端 IP回调时校验速率限制对/oauth/callback接口按 IP 限流如 5 次/分钟。上线后系统拦截了 1200 次重放攻击尝试授权成功率稳定在 98.7%。本文著作权归 微赚淘客系统3.0 研发团队转载请注明出处