ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
@@ -2,9 +2,18 @@ import cn.dev33.satoken.annotation.SaIgnore; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSON; import cn.hutool.json.JSONUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import me.zhyd.oauth.cache.AuthStateCache; import me.zhyd.oauth.model.AuthCallback; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.request.AuthRequest; import me.zhyd.oauth.utils.AuthStateUtils; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.EmailLoginBody; import org.dromara.common.core.domain.model.LoginBody; @@ -13,9 +22,16 @@ import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.social.config.SocialConfig; import org.dromara.common.social.config.properties.ConfigProperties; import org.dromara.common.social.config.properties.SocialProperties; import org.dromara.common.social.utils.AuthRedisStateCache; import org.dromara.common.social.utils.SocialUtils; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.service.ISocialUserService; import org.dromara.system.service.ISysConfigService; import org.dromara.system.service.ISysTenantService; import org.dromara.web.domain.vo.LoginTenantVo; @@ -26,8 +42,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Map; /** * è®¤è¯ @@ -41,10 +59,14 @@ @RequestMapping("/auth") public class AuthController { private final SocialProperties socialProperties; private final SysLoginService loginService; private final SysRegisterService registerService; private final ISysConfigService configService; private final ISysTenantService tenantService; private final ISocialUserService socialUserService; /** * ç»å½æ¹æ³ @@ -115,6 +137,71 @@ return R.ok(loginVo); } /** * è®¤è¯ææ * @param source */ @GetMapping("/binding/{source}") @ResponseBody public R<LoginVo> authBinding(@PathVariable("source") String source, HttpServletRequest request){ SysUserVo userLoding = new SysUserVo(); if (ObjectUtil.isNull(userLoding)) { return R.fail("ææå¤±è´¥ï¼è¯·å ç»å½åç»å®"); } if (socialUserService.isExistByUserIdAndSource(userLoding.getUserId(),source)) { return R.fail(source + "å¹³å°è´¦å·å·²ç»è¢«è´¦å·ç»å®"); } ConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)){ return R.fail(source + "å¹³å°è´¦å·æä¸æ¯æ"); } AuthRequest authRequest = SocialUtils.getAuthRequest(source, obj.getClientId(), obj.getClientSecret(), obj.getRedirectUri()); String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); return R.ok(authorizeUrl); } /** * ç¬¬ä¸æ¹ç»å½åè°ä¸å¡å¤ç * @param source * @param callback * @param request * @return */ @SuppressWarnings("unchecked") @GetMapping("/social-login/{source}") public R<String> socialLogin(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request) throws IOException { ConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)){ return R.fail(source + "å¹³å°è´¦å·æä¸æ¯æ"); } AuthRequest authRequest = SocialUtils.getAuthRequest(source, obj.getClientId(), obj.getClientSecret(), obj.getRedirectUri()); AuthResponse<AuthUser> response = authRequest.login(callback); return loginService.socialLogin(source, response, request); } /** * åæ¶ææ * @param socialId */ @DeleteMapping(value = "/unlock/{socialId}") public R<Void> unlockSocial(@PathVariable Long socialId) { Boolean rows = socialUserService.deleteWithValidById(socialId); return rows ? R.ok() : R.fail("åæ¶ææå¤±è´¥"); } /** * éåºç»å½ */ ruoyi-admin/src/main/resources/application-dev.yml
@@ -169,3 +169,151 @@ signName: æµè¯ # è ¾è®¯ä¸ç¨ sdkAppId: justauth: enabled: true type: QQ: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/qq/callback union-id: false WEIBO: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/weibo/callback gitee: client-id: 38eaaa1b77b5e064313057a2f5745ce3a9f3e7686d9bd302c7df2f308ef6db81 client-secret: 2e633af8780cb9fe002c4c7291b722db944402e271efb99b062811f52d7da1ff redirect-uri: http://localhost:8888/social-login?source=gitee DINGTALK: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/dingtalk/callback BAIDU: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/baidu/callback CSDN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/csdn/callback CODING: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/coding/callback coding-group-name: xx OSCHINA: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/oschina/callback ALIPAY: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/alipay/callback alipay-public-key: MIIB**************DAQAB WECHAT_OPEN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_open/callback WECHAT_MP: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_mp/callback WECHAT_ENTERPRISE: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_enterprise/callback agent-id: 1000002 TAOBAO: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/taobao/callback GOOGLE: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/google/callback FACEBOOK: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/facebook/callback DOUYIN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/douyin/callback LINKEDIN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/linkedin/callback MICROSOFT: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/microsoft/callback MI: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/mi/callback TOUTIAO: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/toutiao/callback TEAMBITION: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/teambition/callback RENREN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/renren/callback PINTEREST: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/pinterest/callback STACK_OVERFLOW: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/stack_overflow/callback stack-overflow-key: asd*********asd HUAWEI: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/huawei/callback KUJIALE: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/kujiale/callback GITLAB: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/gitlab/callback MEITUAN: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/meituan/callback ELEME: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/eleme/callback TWITTER: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/twitter/callback XMLY: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/xmly/callback # 设å¤å¯ä¸æ è¯ID device-id: xxxxxxxxxxxxxx # 客æ·ç«¯æä½ç³»ç»ç±»åï¼1-iOSç³»ç»ï¼2-Androidç³»ç»ï¼3-Web client-os-type: 3 # 客æ·ç«¯å åï¼å¦æ clientOsType 为1æ2æ¶å¿ å¡«ã对Android客æ·ç«¯æ¯å åï¼å¯¹IOS客æ·ç«¯æ¯Bundle ID #pack-id: xxxx FEISHU: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/feishu/callback JD: client-id: 10**********6 client-secret: 1f7d08**********5b7**********29e redirect-uri: http://oauth.xkcoding.com/demo/oauth/jd/callback ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/DeviceType.java
@@ -26,7 +26,12 @@ /** * å°ç¨åºç«¯ */ XCX("xcx"); XCX("xcx"), /** * socialç¬¬ä¸æ¹ç«¯ */ SOCIAL("social"); private final String device; } ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/ConfigProperties.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,58 @@ package org.dromara.common.social.config.properties; import lombok.Data; @Data public class ConfigProperties { /** * åºç¨ ID */ private String clientId; /** * åºç¨å¯é¥ */ private String clientSecret; /** * åè°å°å */ private String redirectUri; /** * æ¯å¦è·åunionId */ private boolean unionId; /** * Coding ä¼ä¸åç§° */ private String codingGroupName; /** * æ¯ä»å®å ¬é¥ */ private String alipayPublicKey; /** * ä¼ä¸å¾®ä¿¡åºç¨ID */ private String agentId; /** * stackoverflow api key */ private String stackOverflowKey; /** * 设å¤ID */ private String deviceId; /** * 客æ·ç«¯ç³»ç»ç±»å */ private String clientOsType; } ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,79 @@ package org.dromara.common.social.utils; import jakarta.annotation.PostConstruct; import me.zhyd.oauth.cache.AuthStateCache; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.social.config.properties.SocialProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import java.time.Duration; public class AuthRedisStateCache implements AuthStateCache { private final SocialProperties socialProperties; private final RedisTemplate<String, String> redisTemplate; private ValueOperations<String, String> valueOperations; @PostConstruct public void init() { valueOperations = redisTemplate.opsForValue(); } public AuthRedisStateCache() { this.socialProperties = new SocialProperties(); redisTemplate = new RedisTemplate<>(); } /** * åå ¥ç¼å * * @param key ç¼åkey * @param value ç¼åå 容 */ @Override public void cache(String key, String value) { // TODO: èªå®ä¹åå ¥ç¼å RedisUtils.setCacheObject(key, value, Duration.ofMillis(socialProperties.getTimeout())); } /** * åå ¥ç¼å * * @param key ç¼åkey * @param value ç¼åå 容 * @param timeout æå®ç¼åè¿ææ¶é´(毫ç§) */ @Override public void cache(String key, String value, long timeout) { // TODO: èªå®ä¹åå ¥ç¼å RedisUtils.setCacheObject(key, value, Duration.ofMillis(timeout)); } /** * è·åç¼åå 容 * * @param key ç¼åkey * @return ç¼åå 容 */ @Override public String get(String key) { // TODO: èªå®ä¹è·åç¼åå 容 return RedisUtils.getCacheObject(key); } /** * æ¯å¦åå¨keyï¼å¦æå¯¹åºkeyçvalueå¼å·²è¿æï¼ä¹è¿åfalse * * @param key ç¼åkey * @return trueï¼åå¨keyï¼å¹¶ä¸valueæ²¡è¿æï¼falseï¼keyä¸å卿è å·²è¿æ */ @Override public boolean containsKey(String key) { // TODO: èªå®ä¹å¤ækeyæ¯å¦åå¨ return RedisUtils.hasKey(key); } }