Commit e05d90590ef2731a81568b2a11b0aa097c23dbdf

Authored by YunaiV
1 parent a56b4a7c

接入 dingtalk 钉钉的三方登陆,流程未接入

yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth;
2 2
3 -import cn.hutool.core.net.url.UrlBuilder;  
4 -import cn.hutool.http.HttpUtil;  
5 import cn.hutool.json.JSONUtil; 3 import cn.hutool.json.JSONUtil;
6 -import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum;  
7 -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;  
8 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
9 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
10 -import cn.iocoder.yudao.framework.common.util.http.HttpUtils;  
11 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
12 -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;  
13 -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO;  
14 -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO;  
15 -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; 4 +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.*;
16 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; 5 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
17 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; 6 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
18 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
19 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
20 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum; 9 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum;
  10 +import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum;
21 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; 11 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
22 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 12 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
23 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
24 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  15 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  16 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
25 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 17 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
26 -import com.aliyuncs.CommonResponse; 18 +import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
  19 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
27 import com.xkcoding.justauth.AuthRequestFactory; 20 import com.xkcoding.justauth.AuthRequestFactory;
28 import io.swagger.annotations.Api; 21 import io.swagger.annotations.Api;
29 import io.swagger.annotations.ApiImplicitParam; 22 import io.swagger.annotations.ApiImplicitParam;
@@ -35,26 +28,18 @@ import me.zhyd.oauth.model.AuthResponse; @@ -35,26 +28,18 @@ import me.zhyd.oauth.model.AuthResponse;
35 import me.zhyd.oauth.model.AuthUser; 28 import me.zhyd.oauth.model.AuthUser;
36 import me.zhyd.oauth.request.AuthRequest; 29 import me.zhyd.oauth.request.AuthRequest;
37 import me.zhyd.oauth.utils.AuthStateUtils; 30 import me.zhyd.oauth.utils.AuthStateUtils;
38 -import org.apache.commons.lang.StringUtils;  
39 -import org.quartz.SimpleTrigger;  
40 import org.springframework.validation.annotation.Validated; 31 import org.springframework.validation.annotation.Validated;
41 import org.springframework.web.bind.annotation.*; 32 import org.springframework.web.bind.annotation.*;
42 -import org.springframework.web.multipart.MultipartFile;  
43 -import org.springframework.web.util.UriBuilder;  
44 33
45 import javax.annotation.Resource; 34 import javax.annotation.Resource;
46 -import javax.servlet.http.HttpServletResponse;  
47 import javax.validation.Valid; 35 import javax.validation.Valid;
48 -import java.io.IOException;  
49 -import java.net.URL;  
50 -import java.nio.charset.Charset;  
51 import java.util.List; 36 import java.util.List;
52 37
53 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 38 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
54 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;  
55 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds;  
56 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 39 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
57 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; 40 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
  41 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  42 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds;
58 43
59 @Api(tags = "认证") 44 @Api(tags = "认证")
60 @RestController 45 @RestController
@@ -71,8 +56,6 @@ public class SysAuthController { @@ -71,8 +56,6 @@ public class SysAuthController {
71 private SysRoleService roleService; 56 private SysRoleService roleService;
72 @Resource 57 @Resource
73 private SysPermissionService permissionService; 58 private SysPermissionService permissionService;
74 - @Resource  
75 - private SysUserSessionService sysUserSessionService;  
76 59
77 @Resource 60 @Resource
78 private AuthRequestFactory authRequestFactory; 61 private AuthRequestFactory authRequestFactory;
@@ -86,42 +69,6 @@ public class SysAuthController { @@ -86,42 +69,6 @@ public class SysAuthController {
86 return success(SysAuthLoginRespVO.builder().token(token).build()); 69 return success(SysAuthLoginRespVO.builder().token(token).build());
87 } 70 }
88 71
89 - @GetMapping("/third-login-redirect")  
90 - @ApiOperation("三方登陆的跳转")  
91 - @ApiImplicitParams({  
92 - @ApiImplicitParam(name = "type", value = "三方类型", required = true, dataTypeClass = Integer.class),  
93 - @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class)  
94 - })  
95 - public CommonResult<String> login(@RequestParam("type") Integer type,  
96 - @RequestParam("redirectUri") String redirectUri) throws IOException {  
97 - // 获得对应的 AuthRequest 实现  
98 - AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource());  
99 - // 生成跳转地址  
100 - String authorizeUri = authRequest.authorize(AuthStateUtils.createState());  
101 - authorizeUri = HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);  
102 -// authorizeUri = UrlBuilder.fromBaseUrl(authorizeUri).queryParam("redirect_uri", redirectUri).build();  
103 - return CommonResult.success(authorizeUri);  
104 - }  
105 -  
106 - @RequestMapping("/{type}/callback")  
107 - public AuthResponse login(@PathVariable String type, AuthCallback callback) {  
108 - AuthRequest authRequest = authRequestFactory.get(type);  
109 - AuthResponse<AuthUser> response = authRequest.login(callback);  
110 - log.info("【response】= {}", JSONUtil.toJsonStr(response));  
111 - return response;  
112 - }  
113 -  
114 -// @RequestMapping("/auth2/login/{oauthType}")  
115 -// @ApiOperation("第三方登录")  
116 -// @OperateLog(enable = false) // 避免 Post 请求被记录操作日志  
117 -// public CommonResult<SysAuthLoginRespVO> login(@PathVariable String oauthType) {  
118 -// Authentication authentication = SecurityContextHolder.getContext().getAuthentication();  
119 -// //TODO NPE  
120 -// String token = sysUserSessionService.getSessionId(authentication.getName());  
121 -// // 返回结果  
122 -// return success(SysAuthLoginRespVO.builder().token(token).build());  
123 -// }  
124 -  
125 @GetMapping("/get-permission-info") 72 @GetMapping("/get-permission-info")
126 @ApiOperation("获取登陆用户的权限信息") 73 @ApiOperation("获取登陆用户的权限信息")
127 public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() { 74 public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
@@ -153,4 +100,38 @@ public class SysAuthController { @@ -153,4 +100,38 @@ public class SysAuthController {
153 return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList)); 100 return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList));
154 } 101 }
155 102
  103 + // ========== 三方登陆相关 ==========
  104 +
  105 + @GetMapping("/third-login-redirect")
  106 + @ApiOperation("三方登陆的跳转")
  107 + @ApiImplicitParams({
  108 + @ApiImplicitParam(name = "type", value = "三方类型", required = true, dataTypeClass = Integer.class),
  109 + @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class)
  110 + })
  111 + public CommonResult<String> thirdLoginRedirect(@RequestParam("type") Integer type,
  112 + @RequestParam("redirectUri") String redirectUri) {
  113 + // 获得对应的 AuthRequest 实现
  114 + AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource());
  115 + // 生成跳转地址
  116 + String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
  117 + authorizeUri = HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
  118 + return CommonResult.success(authorizeUri);
  119 + }
  120 +
  121 + @PostMapping("/third-login")
  122 + @ApiOperation("三方登陆,使用 code 授权码")
  123 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  124 + public CommonResult<SysAuthLoginRespVO> thirdLogin(@RequestBody @Valid SysAuthThirdLoginReqVO reqVO) {
  125 + String token = authService.thirdLogin(reqVO, getClientIP(), getUserAgent());
  126 + return null;
  127 + }
  128 +
  129 + @RequestMapping("/{type}/callback")
  130 + public AuthResponse login(@PathVariable String type, AuthCallback callback) {
  131 + AuthRequest authRequest = authRequestFactory.get(type);
  132 + AuthResponse<AuthUser> response = authRequest.login(callback);
  133 + log.info("【response】= {}", JSONUtil.toJsonStr(response));
  134 + return response;
  135 + }
  136 +
156 } 137 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthThirdLoginReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import io.swagger.annotations.ApiModel;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import lombok.AllArgsConstructor;
  8 +import lombok.Builder;
  9 +import lombok.Data;
  10 +import lombok.NoArgsConstructor;
  11 +import org.hibernate.validator.constraints.Length;
  12 +
  13 +import javax.validation.constraints.NotEmpty;
  14 +import javax.validation.constraints.NotNull;
  15 +import javax.validation.constraints.Pattern;
  16 +
  17 +@ApiModel("三方登陆 Request VO,使用 code 授权码")
  18 +@Data
  19 +@NoArgsConstructor
  20 +@AllArgsConstructor
  21 +@Builder
  22 +public class SysAuthThirdLoginReqVO {
  23 +
  24 + @ApiModelProperty(value = "三方平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
  25 + @InEnum(SysUserSocialTypeEnum.class)
  26 + @NotNull(message = "三方平台的类型不能为空")
  27 + private Integer type;
  28 +
  29 + @ApiModelProperty(value = "授权码", required = true, example = "1024")
  30 + @NotEmpty(message = "授权码不能为空")
  31 + private String code;
  32 +
  33 + @ApiModelProperty(value = "state", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
  34 + @NotEmpty(message = "state 不能为空")
  35 + private String state;
  36 +
  37 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.system.convert.auth; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.system.convert.auth;
2 2
3 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; 3 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO;
4 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; 4 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO;
5 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
7 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO;
@@ -11,6 +12,7 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO @@ -11,6 +12,7 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO
11 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; 12 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum;
12 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 13 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
13 import cn.iocoder.yudao.framework.security.core.LoginUser; 14 import cn.iocoder.yudao.framework.security.core.LoginUser;
  15 +import me.zhyd.oauth.model.AuthCallback;
14 import me.zhyd.oauth.model.AuthUser; 16 import me.zhyd.oauth.model.AuthUser;
15 import org.mapstruct.Mapper; 17 import org.mapstruct.Mapper;
16 import org.mapstruct.Mapping; 18 import org.mapstruct.Mapping;
@@ -43,6 +45,8 @@ public interface SysAuthConvert { @@ -43,6 +45,8 @@ public interface SysAuthConvert {
43 45
44 LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO); 46 LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO);
45 47
  48 + AuthCallback convert(SysAuthThirdLoginReqVO bean);
  49 +
46 /** 50 /**
47 * 将菜单列表,构建成菜单树 51 * 将菜单列表,构建成菜单树
48 * 52 *
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/user/SysUserSocialDO.java
@@ -41,6 +41,7 @@ public class SysUserSocialDO extends BaseDO { @@ -41,6 +41,7 @@ public class SysUserSocialDO extends BaseDO {
41 * 三方平台的类型 41 * 三方平台的类型
42 */ 42 */
43 private SysUserSocialTypeEnum type; 43 private SysUserSocialTypeEnum type;
  44 +
44 /** 45 /**
45 * 三方 openid 46 * 三方 openid
46 */ 47 */
@@ -56,6 +57,10 @@ public class SysUserSocialDO extends BaseDO { @@ -56,6 +57,10 @@ public class SysUserSocialDO extends BaseDO {
56 * 如果没有 unionId 的平台,直接使用 openid 作为该字段的值 57 * 如果没有 unionId 的平台,直接使用 openid 作为该字段的值
57 */ 58 */
58 private String unionId; 59 private String unionId;
  60 + /**
  61 + * 原始 Token 数据,一般是 JSON 格式
  62 + */
  63 + private String rawTokenInfo;
59 64
60 /** 65 /**
61 * 用户昵称 66 * 用户昵称
@@ -66,9 +71,9 @@ public class SysUserSocialDO extends BaseDO { @@ -66,9 +71,9 @@ public class SysUserSocialDO extends BaseDO {
66 */ 71 */
67 private String avatar; 72 private String avatar;
68 /** 73 /**
69 - * 原始数据,一般是 JSON 格式 74 + * 原始用户数据,一般是 JSON 格式
70 */ 75 */
71 - private String info; 76 + private String rawUserInfo;
72 77
73 } 78 }
74 79
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/user/SysUserSocialTypeEnum.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.enums.user; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.enums.user;
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
4 import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; 4 import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum;
5 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 5 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  6 +import com.fasterxml.jackson.annotation.JsonCreator;
6 import jodd.util.ArraysUtil; 7 import jodd.util.ArraysUtil;
7 import lombok.AllArgsConstructor; 8 import lombok.AllArgsConstructor;
8 import lombok.Getter; 9 import lombok.Getter;
@@ -19,6 +20,7 @@ import java.util.Arrays; @@ -19,6 +20,7 @@ import java.util.Arrays;
19 public enum SysUserSocialTypeEnum implements IntArrayValuable { 20 public enum SysUserSocialTypeEnum implements IntArrayValuable {
20 21
21 GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/ 22 GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/
  23 + DINGTALK(20, "DINGTALK"), // https://developers.dingtalk.com/document/app/obtain-identity-credentials
22 ; 24 ;
23 25
24 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysUserSocialTypeEnum::getType).toArray(); 26 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysUserSocialTypeEnum::getType).toArray();
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO;
3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 4 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
4 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
5 6
@@ -22,4 +23,14 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -22,4 +23,14 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
22 */ 23 */
23 String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent); 24 String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent);
24 25
  26 + /**
  27 + * 三方登陆用户,使用 code 授权码
  28 + *
  29 + * @param reqVO 登陆信息
  30 + * @param userIp 用户 IP
  31 + * @param userAgent 用户 UA
  32 + * @return 身份令牌,使用 JWT 方式
  33 + */
  34 + String thirdLogin(SysAuthThirdLoginReqVO reqVO, String userIp, String userAgent);
  35 +
25 } 36 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
2 2
  3 +import cn.hutool.json.JSONUtil;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 7 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  8 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 import cn.iocoder.yudao.framework.security.core.LoginUser; 9 import cn.iocoder.yudao.framework.security.core.LoginUser;
6 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 10 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; 11 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
@@ -17,7 +21,12 @@ import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogSer @@ -17,7 +21,12 @@ import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogSer
17 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 21 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
18 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 22 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
19 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 23 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
  24 +import com.xkcoding.justauth.AuthRequestFactory;
20 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
  26 +import me.zhyd.oauth.model.AuthCallback;
  27 +import me.zhyd.oauth.model.AuthResponse;
  28 +import me.zhyd.oauth.model.AuthUser;
  29 +import me.zhyd.oauth.request.AuthRequest;
21 import org.springframework.context.annotation.Lazy; 30 import org.springframework.context.annotation.Lazy;
22 import org.springframework.security.authentication.AuthenticationManager; 31 import org.springframework.security.authentication.AuthenticationManager;
23 import org.springframework.security.authentication.BadCredentialsException; 32 import org.springframework.security.authentication.BadCredentialsException;
@@ -60,6 +69,9 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -60,6 +69,9 @@ public class SysAuthServiceImpl implements SysAuthService {
60 @Resource 69 @Resource
61 private SysUserSessionService userSessionService; 70 private SysUserSessionService userSessionService;
62 71
  72 + @Resource
  73 + private AuthRequestFactory authRequestFactory;
  74 +
63 @Override 75 @Override
64 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 76 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
65 // 获取 username 对应的 SysUserDO 77 // 获取 username 对应的 SysUserDO
@@ -97,6 +109,24 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -97,6 +109,24 @@ public class SysAuthServiceImpl implements SysAuthService {
97 return userSessionService.createUserSession(loginUser, userIp, userAgent); 109 return userSessionService.createUserSession(loginUser, userIp, userAgent);
98 } 110 }
99 111
  112 + @Override
  113 + public String thirdLogin(SysAuthThirdLoginReqVO reqVO, String userIp, String userAgent) {
  114 + // 使用 code 授权码,进行登陆
  115 + AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(reqVO.getType()).getSource());
  116 + AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO);
  117 + AuthResponse<?> authResponse = authRequest.login(authCallback);
  118 + log.info("[thirdLogin][请求三方平台 type({}) request({}) response({})]", reqVO.getType(), JsonUtils.toJsonString(authCallback),
  119 + JsonUtils.toJsonString(authResponse));
  120 + if (!authResponse.ok()) {
  121 + throw new RuntimeException(""); // TODO 芋艿:补全
  122 + }
  123 + AuthUser authUser = (AuthUser) authResponse.getData();
  124 +
  125 + // 查找到对应的
  126 +
  127 + return null;
  128 + }
  129 +
100 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { 130 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
101 String code = captchaService.getCaptchaCode(captchaUUID); 131 String code = captchaService.getCaptchaCode(captchaUUID);
102 // 验证码不存在 132 // 验证码不存在
yudao-admin-server/src/main/resources/application-local.yaml
@@ -173,8 +173,12 @@ justauth: @@ -173,8 +173,12 @@ justauth:
173 type: 173 type:
174 GITEE: 174 GITEE:
175 client-id: 6bb0b37a8a017e5e2dc4c34ca4756dcf80e8e392585e7035d3ede7a6db50426e 175 client-id: 6bb0b37a8a017e5e2dc4c34ca4756dcf80e8e392585e7035d3ede7a6db50426e
176 - client-secret: f117b9de5e9267bcd48db83d4cb078ea8cf9a5d17cda83481e3d9090df3fa01d 176 + client-secret: ba9f1f42e77be71f461b54da83b6f4b45a052dd7f93418f00f91f4e6934dfd1f
177 ignore-check-redirect-uri: true 177 ignore-check-redirect-uri: true
178 # redirect-uri: http://127.0.0.1:48080/api/gitee/callback 178 # redirect-uri: http://127.0.0.1:48080/api/gitee/callback
  179 + DINGTALK:
  180 + client-id: dingvrnreaje3yqvzhxg
  181 + client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI
  182 + ignore-check-redirect-uri: true
179 cache: 183 cache:
180 type: default 184 type: default
yudao-admin-ui/src/api/login.js
@@ -39,18 +39,23 @@ export function getCodeImg() { @@ -39,18 +39,23 @@ export function getCodeImg() {
39 }) 39 })
40 } 40 }
41 41
42 -// 接入第三方登录  
43 -export function oAuthLogin(type, redirectUri) { 42 +// 三方登陆的跳转
  43 +export function thirdLoginRedirect(type, redirectUri) {
44 return request({ 44 return request({
45 url: '/third-login-redirect?type=' + type + '&redirectUri=' + redirectUri, 45 url: '/third-login-redirect?type=' + type + '&redirectUri=' + redirectUri,
46 method: 'get' 46 method: 'get'
47 }) 47 })
48 } 48 }
49 49
50 -export function getToken(path) {  
51 - console.log({path}); 50 +// 三方登陆,使用 code 授权码
  51 +export function thirdLogin(type, code, state) {
52 return request({ 52 return request({
53 - url: '/auth2/login/github' + path,  
54 - method: 'get' 53 + url: '/third-login',
  54 + method: 'post',
  55 + data: {
  56 + type,
  57 + code,
  58 + state
  59 + }
55 }) 60 })
56 } 61 }
yudao-admin-ui/src/permission.js
@@ -7,7 +7,7 @@ import { getToken } from &#39;@/utils/auth&#39; @@ -7,7 +7,7 @@ import { getToken } from &#39;@/utils/auth&#39;
7 7
8 NProgress.configure({ showSpinner: false }) 8 NProgress.configure({ showSpinner: false })
9 9
10 -const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee'] 10 +const whiteList = ['/login', '/third-login', '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee']
11 11
12 router.beforeEach((to, from, next) => { 12 router.beforeEach((to, from, next) => {
13 NProgress.start() 13 NProgress.start()
yudao-admin-ui/src/router/index.js
@@ -44,8 +44,8 @@ export const constantRoutes = [ @@ -44,8 +44,8 @@ export const constantRoutes = [
44 hidden: true 44 hidden: true
45 }, 45 },
46 { 46 {
47 - path: '/oauthLogin/gitee',  
48 - component: (resolve) => require(['@/views/oauthLogin'], resolve), 47 + path: '/third-login',
  48 + component: (resolve) => require(['@/views/thirdLogin'], resolve),
49 hidden: true 49 hidden: true
50 }, 50 },
51 { 51 {
yudao-admin-ui/src/utils/constants.js
@@ -66,3 +66,11 @@ export const InfApiErrorLogProcessStatusEnum = { @@ -66,3 +66,11 @@ export const InfApiErrorLogProcessStatusEnum = {
66 DONE: 1, // 已处理 66 DONE: 1, // 已处理
67 IGNORE: 2, // 已忽略 67 IGNORE: 2, // 已忽略
68 } 68 }
  69 +
  70 +/**
  71 + * 用户的三方平台的类型枚举
  72 + */
  73 +export const SysUserSocialTypeEnum = {
  74 + GITEE: 10,
  75 + DINGTALK: 20,
  76 +}
yudao-admin-ui/src/views/login.vue
@@ -45,7 +45,7 @@ @@ -45,7 +45,7 @@
45 </template> 45 </template>
46 46
47 <script> 47 <script>
48 -import { getCodeImg,oAuthLogin } from "@/api/login"; 48 +import { getCodeImg,thirdLoginRedirect } from "@/api/login";
49 import Cookies from "js-cookie"; 49 import Cookies from "js-cookie";
50 import { encrypt, decrypt } from '@/utils/jsencrypt' 50 import { encrypt, decrypt } from '@/utils/jsencrypt'
51 51
@@ -54,7 +54,6 @@ export default { @@ -54,7 +54,6 @@ export default {
54 data() { 54 data() {
55 return { 55 return {
56 codeUrl: "", 56 codeUrl: "",
57 - cookiePassword: "",  
58 loginForm: { 57 loginForm: {
59 username: "admin", 58 username: "admin",
60 password: "admin123", 59 password: "admin123",
@@ -68,13 +67,10 @@ export default { @@ -68,13 +67,10 @@ export default {
68 source: "gitee", 67 source: "gitee",
69 type: 10 68 type: 10
70 }, { 69 }, {
71 - img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/wechat.png",  
72 - title: "微信",  
73 - source: "weixin"  
74 - }, {  
75 - img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/qq.png",  
76 - title: "QQ",  
77 - source: "qq" 70 + img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/dingtalk.png",
  71 + title: "钉钉",
  72 + source: "dingtalk",
  73 + type: 20
78 } 74 }
79 ], 75 ],
80 loginRules: { 76 loginRules: {
@@ -147,9 +143,11 @@ export default { @@ -147,9 +143,11 @@ export default {
147 // 设置登陆中 143 // 设置登陆中
148 this.loading = true; 144 this.loading = true;
149 // 计算 redirectUri 145 // 计算 redirectUri
150 - const redirectUri = location.origin + '/third-login'; 146 + // const redirectUri = location.origin + '/third-login';
  147 + // const redirectUri = 'http://127.0.0.1:48080/api/gitee/callback';
  148 + const redirectUri = 'http://127.0.0.1:48080/api/dingtalk/callback';
151 // 进行跳转 149 // 进行跳转
152 - oAuthLogin(provider.type, redirectUri).then((res) => { 150 + thirdLoginRedirect(provider.type, redirectUri).then((res) => {
153 // console.log(res.url); 151 // console.log(res.url);
154 window.location.href = res.data; 152 window.location.href = res.data;
155 }); 153 });
yudao-admin-ui/src/views/oauthLogin.vue deleted
1 -<template>  
2 -</template>  
3 -  
4 -<script>  
5 -import { setToken } from '@/utils/auth'  
6 -  
7 -export default {  
8 - created() {  
9 - const {token} = this.$route.query;  
10 - setToken(token);  
11 - this.$router.push({ path: this.redirect || "/" }).catch(() => {});  
12 - },  
13 -}  
14 -</script>  
15 -  
16 -<style>  
17 -  
18 -</style>  
yudao-admin-ui/src/views/thirdLogin.vue 0 → 100644
  1 +<template>
  2 + <div class="login">
  3 + <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
  4 + <h3 class="title">绑定账号</h3>
  5 + <el-form-item prop="username">
  6 + <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
  7 + <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
  8 + </el-input>
  9 + </el-form-item>
  10 + <el-form-item prop="password">
  11 + <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin">
  12 + <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
  13 + </el-input>
  14 + </el-form-item>
  15 + <el-form-item style="width:100%;">
  16 + <el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
  17 + <span v-if="!loading">提 交</span>
  18 + <span v-else>提 交 中...</span>
  19 + </el-button>
  20 + </el-form-item>
  21 +
  22 + </el-form>
  23 + <!-- 底部 -->
  24 + <div class="el-login-footer">
  25 + <span>Copyright © 2020-2021 iocoder.cn All Rights Reserved.</span>
  26 + </div>
  27 + </div>
  28 +</template>
  29 +
  30 +<script>
  31 +import { thirdLogin } from "@/api/login";
  32 +import Cookies from "js-cookie";
  33 +import { encrypt, decrypt } from '@/utils/jsencrypt'
  34 +
  35 +export default {
  36 + name: "ThirdLogin",
  37 + data() {
  38 + return {
  39 + loginForm: {
  40 + username: "admin",
  41 + password: "admin123",
  42 + rememberMe: false,
  43 + },
  44 + loginRules: {
  45 + username: [
  46 + { required: true, trigger: "blur", message: "用户名不能为空" }
  47 + ],
  48 + password: [
  49 + { required: true, trigger: "blur", message: "密码不能为空" }
  50 + ],
  51 + },
  52 + loading: false,
  53 + redirect: undefined,
  54 + // 三方登陆相关
  55 + type: undefined,
  56 + code: undefined,
  57 + state: undefined,
  58 + };
  59 + },
  60 + watch: {
  61 + $route: {
  62 + handler: function(route) {
  63 + this.redirect = route.query && route.query.redirect;
  64 + },
  65 + immediate: true
  66 + }
  67 + },
  68 + created() {
  69 + this.getCookie();
  70 + // 三方登陆相关
  71 + this.type = 10;
  72 + this.code = this.$route.query.code;
  73 + this.state = this.$route.query.state;
  74 + thirdLogin(this.type, this.code, this.state).then(res => {
  75 + debugger
  76 + });
  77 + },
  78 + methods: {
  79 + getCookie() {
  80 + const username = Cookies.get("username");
  81 + const password = Cookies.get("password");
  82 + const rememberMe = Cookies.get('rememberMe')
  83 + this.loginForm = {
  84 + username: username === undefined ? this.loginForm.username : username,
  85 + password: password === undefined ? this.loginForm.password : decrypt(password),
  86 + rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
  87 + };
  88 + },
  89 + handleLogin() {
  90 + this.$refs.loginForm.validate(valid => {
  91 + if (valid) {
  92 + this.loading = true;
  93 + if (this.loginForm.rememberMe) {
  94 + Cookies.set("username", this.loginForm.username, { expires: 30 });
  95 + Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
  96 + } else {
  97 + Cookies.remove("username");
  98 + Cookies.remove("password");
  99 + }
  100 + this.$store.dispatch("Login", this.loginForm).then(() => {
  101 + this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
  102 + }).catch(() => {
  103 + this.loading = false;
  104 + });
  105 + }
  106 + });
  107 + }
  108 + }
  109 +};
  110 +</script>
  111 +
  112 +<style rel="stylesheet/scss" lang="scss">
  113 +.login {
  114 + display: flex;
  115 + justify-content: center;
  116 + align-items: center;
  117 + height: 100%;
  118 + background-image: url("http://static.yudao.iocoder.cn/login-background.jpg");
  119 + background-size: cover;
  120 +}
  121 +.title {
  122 + margin: 0px auto 30px auto;
  123 + text-align: center;
  124 + color: #707070;
  125 +}
  126 +
  127 +.login-form {
  128 + border-radius: 6px;
  129 + background: #ffffff;
  130 + width: 400px;
  131 + padding: 25px 25px 5px 25px;
  132 + .el-input {
  133 + height: 38px;
  134 + input {
  135 + height: 38px;
  136 + }
  137 + }
  138 + .input-icon {
  139 + height: 39px;
  140 + width: 14px;
  141 + margin-left: 2px;
  142 + }
  143 +}
  144 +.login-tip {
  145 + font-size: 13px;
  146 + text-align: center;
  147 + color: #bfbfbf;
  148 +}
  149 +.login-code {
  150 + width: 33%;
  151 + height: 38px;
  152 + float: right;
  153 + img {
  154 + cursor: pointer;
  155 + vertical-align: middle;
  156 + }
  157 +}
  158 +.el-login-footer {
  159 + height: 40px;
  160 + line-height: 40px;
  161 + position: fixed;
  162 + bottom: 0;
  163 + width: 100%;
  164 + text-align: center;
  165 + color: #fff;
  166 + font-family: Arial;
  167 + font-size: 12px;
  168 + letter-spacing: 1px;
  169 +}
  170 +.login-code-img {
  171 + height: 38px;
  172 +}
  173 +</style>