/* * Copyright (c) 2019-2029, xkcoding & Yangkai.Shen & 沈扬凯 (237497819@qq.com & xkcoding.com). *

* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.gnu.org/licenses/lgpl.html *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package cn.iocoder.yudao.module.system.framework.justauth.core; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import com.xkcoding.http.config.HttpConfig; import com.xkcoding.justauth.autoconfigure.ExtendProperties; import com.xkcoding.justauth.autoconfigure.JustAuthProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.cache.AuthStateCache; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.config.AuthDefaultSource; import me.zhyd.oauth.config.AuthSource; import me.zhyd.oauth.enums.AuthResponseStatus; import me.zhyd.oauth.exception.AuthException; import me.zhyd.oauth.request.*; import org.springframework.util.CollectionUtils; import java.net.InetSocketAddress; import java.net.Proxy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // TODO @芋艿:等官方发布 1.4.1!!! /** *

* AuthRequest工厂类 *

* * @author yangkai.shen * @date Created in 2019-07-22 14:21 */ @Slf4j @RequiredArgsConstructor public class AuthRequestFactory { private final JustAuthProperties properties; private final AuthStateCache authStateCache; /** * 返回当前Oauth列表 * * @return Oauth列表 */ @SuppressWarnings({"unchecked", "rawtypes"}) public List oauthList() { // 默认列表 List defaultList = new ArrayList<>(properties.getType().keySet()); // 扩展列表 List extendList = new ArrayList<>(); ExtendProperties extend = properties.getExtend(); if (null != extend) { Class enumClass = extend.getEnumClass(); List names = EnumUtil.getNames(enumClass); // 扩展列表 extendList = extend.getConfig() .keySet() .stream() .filter(x -> names.contains(x.toUpperCase())) .collect(Collectors.toList()); } // 合并 return (List) CollUtil.addAll(defaultList, extendList); } /** * 返回AuthRequest对象 * * @param source {@link AuthSource} * @return {@link AuthRequest} */ public AuthRequest get(String source) { if (StrUtil.isBlank(source)) { throw new AuthException(AuthResponseStatus.NO_AUTH_SOURCE); } // 获取 JustAuth 中已存在的 AuthRequest authRequest = getDefaultRequest(source); // 如果获取不到则尝试取自定义的 if (authRequest == null) { authRequest = getExtendRequest(properties.getExtend().getEnumClass(), source); } if (authRequest == null) { throw new AuthException(AuthResponseStatus.UNSUPPORTED); } return authRequest; } /** * 获取自定义的 request * * @param clazz 枚举类 {@link AuthSource} * @param source {@link AuthSource} * @return {@link AuthRequest} */ @SuppressWarnings({"unchecked", "rawtypes"}) private AuthRequest getExtendRequest(Class clazz, String source) { String upperSource = source.toUpperCase(); try { EnumUtil.fromString(clazz, upperSource); } catch (IllegalArgumentException e) { // 无自定义匹配 return null; } Map extendConfig = properties.getExtend().getConfig(); // key 转大写 Map upperConfig = new HashMap<>(6); extendConfig.forEach((k, v) -> upperConfig.put(k.toUpperCase(), v)); ExtendProperties.ExtendRequestConfig extendRequestConfig = upperConfig.get(upperSource); if (extendRequestConfig != null) { // 配置 http config configureHttpConfig(upperSource, extendRequestConfig, properties.getHttpConfig()); Class requestClass = extendRequestConfig.getRequestClass(); if (requestClass != null) { // 反射获取 Request 对象,所以必须实现 2 个参数的构造方法 return ReflectUtil.newInstance(requestClass, (AuthConfig) extendRequestConfig, authStateCache); } } return null; } /** * 获取默认的 Request * * @param source {@link AuthSource} * @return {@link AuthRequest} */ private AuthRequest getDefaultRequest(String source) { AuthDefaultSource authDefaultSource; try { authDefaultSource = EnumUtil.fromString(AuthDefaultSource.class, source.toUpperCase()); } catch (IllegalArgumentException e) { // 无自定义匹配 return null; } AuthConfig config = properties.getType().get(authDefaultSource.name()); // 找不到对应关系,直接返回空 if (config == null) { return null; } // 配置 http config configureHttpConfig(authDefaultSource.name(), config, properties.getHttpConfig()); switch (authDefaultSource) { case GITHUB: return new AuthGithubRequest(config, authStateCache); case WEIBO: return new AuthWeiboRequest(config, authStateCache); case GITEE: return new AuthGiteeRequest(config, authStateCache); case DINGTALK: return new AuthDingTalkRequest(config, authStateCache); case DINGTALK_V2: return new AuthDingTalkV2Request(config, authStateCache); case DINGTALK_ACCOUNT: return new AuthDingTalkAccountRequest(config, authStateCache); case BAIDU: return new AuthBaiduRequest(config, authStateCache); case CSDN: return new AuthCsdnRequest(config, authStateCache); case CODING: return new AuthCodingRequest(config, authStateCache); case OSCHINA: return new AuthOschinaRequest(config, authStateCache); case ALIPAY: return new AuthAlipayRequest(config, authStateCache); case QQ: return new AuthQqRequest(config, authStateCache); case WECHAT_OPEN: return new AuthWeChatOpenRequest(config, authStateCache); case WECHAT_MP: return new AuthWeChatMpRequest(config, authStateCache); case TAOBAO: return new AuthTaobaoRequest(config, authStateCache); case GOOGLE: return new AuthGoogleRequest(config, authStateCache); case FACEBOOK: return new AuthFacebookRequest(config, authStateCache); case DOUYIN: return new AuthDouyinRequest(config, authStateCache); case LINKEDIN: return new AuthLinkedinRequest(config, authStateCache); case MICROSOFT: return new AuthMicrosoftRequest(config, authStateCache); case MICROSOFT_CN: return new AuthMicrosoftCnRequest(config, authStateCache); case MI: return new AuthMiRequest(config, authStateCache); case TOUTIAO: return new AuthToutiaoRequest(config, authStateCache); case TEAMBITION: return new AuthTeambitionRequest(config, authStateCache); case RENREN: return new AuthRenrenRequest(config, authStateCache); case PINTEREST: return new AuthPinterestRequest(config, authStateCache); case STACK_OVERFLOW: return new AuthStackOverflowRequest(config, authStateCache); case HUAWEI: return new AuthHuaweiRequest(config, authStateCache); case HUAWEI_V3: return new AuthHuaweiV3Request(config, authStateCache); case WECHAT_ENTERPRISE: return new AuthWeChatEnterpriseQrcodeRequest(config, authStateCache); case WECHAT_ENTERPRISE_V2: return new AuthWeChatEnterpriseQrcodeV2Request(config, authStateCache); case WECHAT_ENTERPRISE_QRCODE_THIRD: return new AuthWeChatEnterpriseThirdQrcodeRequest(config, authStateCache); case WECHAT_ENTERPRISE_WEB: return new AuthWeChatEnterpriseWebRequest(config, authStateCache); case KUJIALE: return new AuthKujialeRequest(config, authStateCache); case GITLAB: return new AuthGitlabRequest(config, authStateCache); case MEITUAN: return new AuthMeituanRequest(config, authStateCache); case ELEME: return new AuthElemeRequest(config, authStateCache); case TWITTER: return new AuthTwitterRequest(config, authStateCache); case FEISHU: return new AuthFeishuRequest(config, authStateCache); case JD: return new AuthJdRequest(config, authStateCache); case ALIYUN: return new AuthAliyunRequest(config, authStateCache); case XMLY: return new AuthXmlyRequest(config, authStateCache); case AMAZON: return new AuthAmazonRequest(config, authStateCache); case SLACK: return new AuthSlackRequest(config, authStateCache); case LINE: return new AuthLineRequest(config, authStateCache); case OKTA: return new AuthOktaRequest(config, authStateCache); case PROGINN: return new AuthProginnRequest(config,authStateCache); case AFDIAN: return new AuthAfDianRequest(config,authStateCache); case APPLE: return new AuthAppleRequest(config,authStateCache); case FIGMA: return new AuthFigmaRequest(config,authStateCache); case WECHAT_MINI_PROGRAM: config.setIgnoreCheckRedirectUri(true); config.setIgnoreCheckState(true); return new AuthWechatMiniProgramRequest(config, authStateCache); case QQ_MINI_PROGRAM: config.setIgnoreCheckRedirectUri(true); config.setIgnoreCheckState(true); return new AuthQQMiniProgramRequest(config, authStateCache); default: return null; } } /** * 配置 http 相关的配置 * * @param authSource {@link AuthSource} * @param authConfig {@link AuthConfig} */ private void configureHttpConfig(String authSource, AuthConfig authConfig, JustAuthProperties.JustAuthHttpConfig httpConfig) { if (null == httpConfig) { return; } Map proxyConfigMap = httpConfig.getProxy(); if (CollectionUtils.isEmpty(proxyConfigMap)) { return; } JustAuthProperties.JustAuthProxyConfig proxyConfig = proxyConfigMap.get(authSource); if (null == proxyConfig) { return; } authConfig.setHttpConfig(HttpConfig.builder() .timeout(httpConfig.getTimeout()) .proxy(new Proxy(Proxy.Type.valueOf(proxyConfig.getType()), new InetSocketAddress(proxyConfig.getHostname(), proxyConfig.getPort()))) .build()); } }