From 33076971fe449fdf4c0b6f6d37c2004d000baf21 Mon Sep 17 00:00:00 2001
From: "yadong.zhang"
* 不建议使用该方式获取授权地址,不带{@code state}的授权地址,容易受到csrf攻击。 * 建议使用{@link AuthDefaultRequest#authorize(String)}方法生成授权地址,在回调方法中对{@code state}进行校验 @@ -75,7 +77,7 @@ public abstract class AuthDefaultRequest implements AuthRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 @@ -150,7 +152,12 @@ public abstract class AuthDefaultRequest implements AuthRequest { * @return 返回不为null的state */ protected String getRealState(String state) { - return StringUtils.isEmpty(state) ? String.valueOf(System.currentTimeMillis()) : state; + if (StringUtils.isEmpty(state)) { + state = UuidUtils.getUUID(); + } + // 缓存state + AuthStateCache.cache(state, state); + return state; } /** diff --git a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java index 6f93286..b01eea5 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java @@ -57,7 +57,7 @@ public class AuthDingTalkRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java b/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java index 618e683..cdab6ae 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java @@ -88,7 +88,7 @@ public class AuthDouyinRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java b/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java index f5e8941..8af2c41 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java @@ -60,7 +60,7 @@ public class AuthGoogleRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java b/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java index 933e2f3..adbb7e6 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java @@ -181,7 +181,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java b/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java index 1d8c60b..3b241e9 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java @@ -108,7 +108,7 @@ public class AuthMiRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java b/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java index 03b8fe7..55227af 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java @@ -101,7 +101,7 @@ public class AuthMicrosoftRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java b/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java index be73c7d..31151d5 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java @@ -69,7 +69,7 @@ public class AuthPinterestRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthRequest.java b/src/main/java/me/zhyd/oauth/request/AuthRequest.java index 4445389..6ceca1e 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthRequest.java @@ -13,7 +13,7 @@ import me.zhyd.oauth.model.AuthToken; public interface AuthRequest { /** - * 返回认证url,可自行跳转页面 + * 返回授权url,可自行跳转页面 *
* 不建议使用该方式获取授权地址,不带{@code state}的授权地址,容易受到csrf攻击。 * 建议使用{@link AuthDefaultRequest#authorize(String)}方法生成授权地址,在回调方法中对{@code state}进行校验 @@ -26,7 +26,7 @@ public interface AuthRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java index a2791c9..ab48453 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java @@ -67,7 +67,7 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthTaobaoRequest.java b/src/main/java/me/zhyd/oauth/request/AuthTaobaoRequest.java index 6468920..3fcdfdf 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthTaobaoRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthTaobaoRequest.java @@ -54,7 +54,7 @@ public class AuthTaobaoRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthTencentCloudRequest.java b/src/main/java/me/zhyd/oauth/request/AuthTencentCloudRequest.java index bedd8a3..7401df8 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthTencentCloudRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthTencentCloudRequest.java @@ -70,7 +70,7 @@ public class AuthTencentCloudRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java b/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java index 3aea926..89926f3 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java @@ -64,7 +64,7 @@ public class AuthToutiaoRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/request/AuthWeChatRequest.java b/src/main/java/me/zhyd/oauth/request/AuthWeChatRequest.java index 913fd64..cf87013 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthWeChatRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthWeChatRequest.java @@ -99,7 +99,7 @@ public class AuthWeChatRequest extends AuthDefaultRequest { } /** - * 返回带{@code state}参数的认证url,授权回调时会带上这个{@code state} + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} * * @param state state 验证授权流程的参数,可以防止csrf * @return 返回授权地址 diff --git a/src/main/java/me/zhyd/oauth/utils/AuthStateUtils.java b/src/main/java/me/zhyd/oauth/utils/AuthStateUtils.java new file mode 100644 index 0000000..4570d7b --- /dev/null +++ b/src/main/java/me/zhyd/oauth/utils/AuthStateUtils.java @@ -0,0 +1,19 @@ +package me.zhyd.oauth.utils; + +/** + * AuthState工具类,默认只提供一个创建随机uuid的方法 + * + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @since 1.9.3 + */ +public class AuthStateUtils { + + /** + * 生成随机state,采用{@see https://github.com/lets-mica/mica}的UUID工具 + * + * @return 随机的state字符串 + */ + public static String createState() { + return UuidUtils.getUUID(); + } +} diff --git a/src/main/java/me/zhyd/oauth/utils/StringUtils.java b/src/main/java/me/zhyd/oauth/utils/StringUtils.java index de22a43..b144bdb 100644 --- a/src/main/java/me/zhyd/oauth/utils/StringUtils.java +++ b/src/main/java/me/zhyd/oauth/utils/StringUtils.java @@ -1,9 +1,11 @@ package me.zhyd.oauth.utils; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ThreadLocalRandom; + /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) - * @version 1.0 - * @since 1.8 + * @since 1.0.0 */ public class StringUtils { @@ -14,4 +16,24 @@ public class StringUtils { public static boolean isNotEmpty(String str) { return !isEmpty(str); } + + /** + * 如果给定字符串{@code str}中不包含{@code appendStr},则在{@code str}后追加{@code appendStr}; + * 如果已包含{@code appendStr},则在{@code str}后追加{@code otherwise} + * + * @param str 给定的字符串 + * @param appendStr 需要追加的内容 + * @param otherwise 当{@code appendStr}不满足时追加到{@code str}后的内容 + * @return 追加后的字符串 + */ + public static String appendIfNotContain(String str, String appendStr, String otherwise) { + if (isEmpty(str) || isEmpty(appendStr)) { + return str; + } + if (str.contains(appendStr)) { + return str.concat(otherwise); + } + return str.concat(appendStr); + } + } diff --git a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java index 54faead..c16ea0c 100644 --- a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java +++ b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java @@ -71,7 +71,7 @@ public class UrlBuilder { if (MapUtil.isEmpty(this.params)) { return this.baseUrl; } - String baseUrl = StrUtil.addSuffixIfNot(this.baseUrl, "?"); + String baseUrl = StringUtils.appendIfNotContain(this.baseUrl, "?", "&"); String paramString = GlobalAuthUtil.parseMapToString(this.params, encode); return baseUrl + paramString; } diff --git a/src/main/java/me/zhyd/oauth/utils/UuidUtils.java b/src/main/java/me/zhyd/oauth/utils/UuidUtils.java new file mode 100644 index 0000000..2782750 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/utils/UuidUtils.java @@ -0,0 +1,65 @@ +package me.zhyd.oauth.utils; + +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 高性能的创建UUID的工具类,{@see https://github.com/lets-mica/mica} + * + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @since 1.9.3 + */ +public class UuidUtils { + + /** + * All possible chars for representing a number as a String + * copy from mica:https://github.com/lets-mica/mica/blob/master/mica-core/src/main/java/net/dreamlu/mica/core/utils/NumberUtil.java#L113 + */ + private final static byte[] DIGITS = { + '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z' + }; + + /** + * 生成uuid,采用 jdk 9 的形式,优化性能 + * copy from mica:https://github.com/lets-mica/mica/blob/master/mica-core/src/main/java/net/dreamlu/mica/core/utils/StringUtil.java#L335 + *
+ * 关于mica uuid生成方式的压测结果,可以参考:https://github.com/lets-mica/mica-jmh/wiki/uuid + * + * @return UUID + */ + public static String getUUID() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + long lsb = random.nextLong(); + long msb = random.nextLong(); + byte[] buf = new byte[32]; + formatUnsignedLong(lsb, buf, 20, 12); + formatUnsignedLong(lsb >>> 48, buf, 16, 4); + formatUnsignedLong(msb, buf, 12, 4); + formatUnsignedLong(msb >>> 16, buf, 8, 4); + formatUnsignedLong(msb >>> 32, buf, 0, 8); + return new String(buf, StandardCharsets.UTF_8); + } + + /** + * copy from mica:https://github.com/lets-mica/mica/blob/master/mica-core/src/main/java/net/dreamlu/mica/core/utils/StringUtil.java#L348 + */ + private static void formatUnsignedLong(long val, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << 4; + int mask = radix - 1; + do { + buf[--charPos] = DIGITS[((int) val) & mask]; + val >>>= 4; + } while (charPos > offset); + } +} diff --git a/src/test/java/me/zhyd/oauth/AuthRequestTest.java b/src/test/java/me/zhyd/oauth/AuthRequestTest.java index f5d26ed..9b50f53 100644 --- a/src/test/java/me/zhyd/oauth/AuthRequestTest.java +++ b/src/test/java/me/zhyd/oauth/AuthRequestTest.java @@ -21,6 +21,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -34,6 +36,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -47,6 +51,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -60,6 +66,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -73,6 +81,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -86,6 +96,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -99,6 +111,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -112,6 +126,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state authRequest.login(new AuthCallback()); } @@ -126,6 +142,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -139,6 +157,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -152,6 +172,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -165,6 +187,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -178,6 +202,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -191,6 +217,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -204,6 +232,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -217,6 +247,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -230,6 +262,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -243,6 +277,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } @@ -256,6 +292,8 @@ public class AuthRequestTest { // 返回授权页面,可自行跳转 authRequest.authorize("state"); // 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参 + // 1.9.3版本后 如果需要验证state,可以在login之前调用{@see AuthCallback#checkState}方法校验state合法性 + // 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state AuthResponse login = authRequest.login(new AuthCallback()); } } diff --git a/src/test/java/me/zhyd/oauth/cache/AuthStateCacheTest.java b/src/test/java/me/zhyd/oauth/cache/AuthStateCacheTest.java new file mode 100644 index 0000000..9c6e1e0 --- /dev/null +++ b/src/test/java/me/zhyd/oauth/cache/AuthStateCacheTest.java @@ -0,0 +1,32 @@ +package me.zhyd.oauth.cache; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +public class AuthStateCacheTest { + + @Test + public void cache1() throws InterruptedException { + AuthStateCache.cache("key", "value"); + Assert.assertEquals(AuthStateCache.get("key"), "value"); + + TimeUnit.MILLISECONDS.sleep(4); + Assert.assertEquals(AuthStateCache.get("key"), "value"); + } + + @Test + public void cache2() throws InterruptedException { + AuthStateCache.cache("key", "value", 10); + Assert.assertEquals(AuthStateCache.get("key"), "value"); + + // 没过期 + TimeUnit.MILLISECONDS.sleep(5); + Assert.assertEquals(AuthStateCache.get("key"), "value"); + + // 过期 + TimeUnit.MILLISECONDS.sleep(6); + Assert.assertNull(AuthStateCache.get("key")); + } +} diff --git a/src/test/java/me/zhyd/oauth/utils/UrlBuilderTest.java b/src/test/java/me/zhyd/oauth/utils/UrlBuilderTest.java index 065c59a..62a4239 100644 --- a/src/test/java/me/zhyd/oauth/utils/UrlBuilderTest.java +++ b/src/test/java/me/zhyd/oauth/utils/UrlBuilderTest.java @@ -3,6 +3,7 @@ package me.zhyd.oauth.utils; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.config.AuthSource; import me.zhyd.oauth.request.AuthWeChatRequest; +import org.junit.Assert; import org.junit.Test; /** @@ -33,4 +34,30 @@ public class UrlBuilderTest { String authorize = request.authorize("state"); System.out.println(authorize); } + + @Test + public void build() { + String url = UrlBuilder.fromBaseUrl("https://www.zhyd.me") + .queryParam("name", "yadong.zhang") + .build(); + Assert.assertEquals(url, "https://www.zhyd.me?name=yadong.zhang"); + + url = UrlBuilder.fromBaseUrl(url) + .queryParam("github", "https://github.com/zhangyd-c") + .build(); + Assert.assertEquals(url, "https://www.zhyd.me?name=yadong.zhang&github=https://github.com/zhangyd-c"); + } + + @Test + public void build1() { + String url = UrlBuilder.fromBaseUrl("https://www.zhyd.me") + .queryParam("name", "yadong.zhang") + .build(true); + Assert.assertEquals(url, "https://www.zhyd.me?name=yadong.zhang"); + + url = UrlBuilder.fromBaseUrl(url) + .queryParam("github", "https://github.com/zhangyd-c") + .build(true); + Assert.assertEquals(url, "https://www.zhyd.me?name=yadong.zhang&github=https%3A%2F%2Fgithub.com%2Fzhangyd-c"); + } } diff --git a/src/test/java/me/zhyd/oauth/utils/UuidUtilsTest.java b/src/test/java/me/zhyd/oauth/utils/UuidUtilsTest.java new file mode 100644 index 0000000..27b8664 --- /dev/null +++ b/src/test/java/me/zhyd/oauth/utils/UuidUtilsTest.java @@ -0,0 +1,13 @@ +package me.zhyd.oauth.utils; + +import org.junit.Test; + +public class UuidUtilsTest { + + @Test + public void getUUID() { + + String uuid = UuidUtils.getUUID(); + System.out.println(uuid); + } +} diff --git a/update.md b/update.md index cc70316..bffbea0 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,11 @@ +### 2019/07/30 ([v1.9.3](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.3)) + +1. 规范注释 +2. 增加State缓存,`AuthCallback`中增加默认的校验state的方法 +3. 增加默认的state生成方法,参考`AuthStateUtils.java`和`UuidUtils.java` +4. 升级`hutool-http`版本到`v4.6.0` +5. 修复其他一些问题 + ### 2019/07/27 1. `IpUtils.getIp`改名为`IpUtils.getLocalIp` -- GitLab