Ver Fonte

:heavy_plus_sign: 新增第三方系统登陆

smallchill há 6 anos atrás
pai
commit
04882685c9
22 ficheiros alterados com 677 adições e 173 exclusões
  1. 0 102
      doc/sql/update/mysql-update-2.4.0~2.5.0.sql
  2. 27 0
      doc/sql/update/mysql-update-2.5.0~2.5.1.sql
  3. 4 0
      pom.xml
  4. 5 56
      src/main/java/org/springblade/modules/auth/controller/AuthController.java
  5. 95 0
      src/main/java/org/springblade/modules/auth/endpoint/BladeSocialEndpoint.java
  6. 90 0
      src/main/java/org/springblade/modules/auth/endpoint/BladeTokenEndPoint.java
  7. 87 0
      src/main/java/org/springblade/modules/auth/granter/SocialTokenGranter.java
  8. 7 6
      src/main/java/org/springblade/modules/auth/granter/TokenGranterBuilder.java
  9. 6 0
      src/main/java/org/springblade/modules/auth/utils/TokenUtil.java
  10. 11 0
      src/main/java/org/springblade/modules/system/controller/UserController.java
  11. 6 0
      src/main/java/org/springblade/modules/system/entity/UserInfo.java
  12. 103 0
      src/main/java/org/springblade/modules/system/entity/UserOauth.java
  13. 29 0
      src/main/java/org/springblade/modules/system/mapper/UserOauthMapper.java
  14. 22 0
      src/main/java/org/springblade/modules/system/mapper/UserOauthMapper.xml
  15. 30 0
      src/main/java/org/springblade/modules/system/service/IUserOauthService.java
  16. 19 1
      src/main/java/org/springblade/modules/system/service/IUserService.java
  17. 36 0
      src/main/java/org/springblade/modules/system/service/impl/UserOauthServiceImpl.java
  18. 58 7
      src/main/java/org/springblade/modules/system/service/impl/UserServiceImpl.java
  19. 6 0
      src/main/resources/application-dev.yml
  20. 5 0
      src/main/resources/application-prod.yml
  21. 5 0
      src/main/resources/application-test.yml
  22. 26 1
      src/main/resources/application.yml

+ 0 - 102
doc/sql/update/mysql-update-2.4.0~2.5.0.sql

@@ -1,102 +0,0 @@
-
--- ----------------------------
--- 增加多租户参数配置
--- ----------------------------
-INSERT INTO `blade_param`(`id`, `param_name`, `param_key`, `param_value`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1238706101399142402, '租户默认管理密码', 'tenant.default.password', 'admin', NULL, 1123598821738675201, 1123598813738675201, '2020-03-14 13:58:43', 1123598821738675201, '2020-03-14 13:58:43', 1, 0);
-INSERT INTO `blade_param`(`id`, `param_name`, `param_key`, `param_value`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1238706160295559170, '租户默认账号额度', 'tenant.default.accountNumber', '100', NULL, 1123598821738675201, 1123598813738675201, '2020-03-14 13:58:57', 1123598821738675201, '2020-03-14 13:58:57', 1, 0);
-INSERT INTO `blade_param`(`id`, `param_name`, `param_key`, `param_value`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1238706330076790786, '租户默认菜单集合', 'tenant.default.menuCode', 'desk,flow,work,monitor,resource,role,user,dept,post,dictbiz,topmenu', NULL, 1123598821738675201, 1123598813738675201, '2020-03-14 13:59:38', 1123598821738675201, '2020-03-14 13:59:38', 1, 0);
-
--- ----------------------------
--- 增加用户表字段
--- ----------------------------
-ALTER TABLE `blade_user`
-    ADD COLUMN `code` varchar(12) NULL COMMENT '用户编号' AFTER `tenant_id`,
-    ADD COLUMN `post_id` varchar(1000) NULL COMMENT '岗位id' AFTER `dept_id`;
-
--- ----------------------------
--- 增加岗位管理表
--- ----------------------------
-CREATE TABLE `blade_post`  (
-  `id` bigint(64) NOT NULL COMMENT '主键',
-  `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '000000' COMMENT '租户ID',
-  `category` int(11) NULL DEFAULT NULL COMMENT '岗位类型',
-  `post_code` varchar(12) NULL COMMENT '岗位编号',
-  `post_name` varchar(64) NULL COMMENT '岗位名称',
-  `sort` int(2) NULL COMMENT '岗位排序',
-  `remark` varchar(255) NULL COMMENT '岗位描述',
-  `create_user` bigint(64) NULL DEFAULT NULL COMMENT '创建人',
-  `create_dept` bigint(64) NULL DEFAULT NULL COMMENT '创建部门',
-  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
-  `update_user` bigint(64) NULL DEFAULT NULL COMMENT '修改人',
-  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
-  `status` int(2) NULL DEFAULT NULL COMMENT '状态',
-  `is_deleted` int(2) NULL DEFAULT NULL COMMENT '是否已删除',
-  PRIMARY KEY (`id`)
-) COMMENT = '岗位表';
-
--- ----------------------------
--- 增加岗位管理表数据
--- ----------------------------
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675201, '000000', 1, 'ceo', '首席执行官', 1, '总经理', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675202, '000000', 1, 'coo', '首席运营官', 2, '常务总经理', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675203, '000000', 1, 'cfo', '首席财务官', 3, '财务总经理', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675204, '000000', 1, 'cto', '首席技术官', 4, '技术总监', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675205, '000000', 1, 'cio', '首席信息官', 5, '信息总监', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675206, '000000', 2, 'pm', '技术经理', 6, '研发和产品是永远的朋友', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675207, '000000', 2, 'hrm', '人力经理', 7, '人力资源部门工作管理者', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-INSERT INTO `blade_post`(`id`, `tenant_id`, `category`, `post_code`, `post_name`, `sort`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`)
-VALUES (1123598817738675208, '000000', 3, 'staff', '普通员工', 8, '普通员工', 1123598821738675201, 1123598813738675201, '2020-04-01 00:00:00', 1123598821738675201, '2020-04-01 00:00:00', 1, 0);
-
--- ----------------------------
--- 增加岗位管理菜单数据
--- ----------------------------
-INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES ('1164733389668962251', '1123598815738675203', 'post', '岗位管理', 'menu', '/system/post', 'iconfont iconicon_message', 2, 1, 0, 1, NULL, 0);
-INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES ('1164733389668962252', '1164733389668962251', 'post_add', '新增', 'add', '/system/post/add', 'plus', 1, 2, 1, 1, NULL, 0);
-INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES ('1164733389668962253', '1164733389668962251', 'post_edit', '修改', 'edit', '/system/post/edit', 'form', 2, 2, 2, 1, NULL, 0);
-INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES ('1164733389668962254', '1164733389668962251', 'post_delete', '删除', 'delete', '/api/blade-system/post/remove', 'delete', 3, 2, 3, 1, NULL, 0);
-INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES ('1164733389668962255', '1164733389668962251', 'post_view', '查看', 'view', '/system/post/view', 'file-text', 4, 2, 2, 1, NULL, 0);
-
--- ----------------------------
--- 增加岗位管理菜单权限数据
--- ----------------------------
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225001', '1164733389668962251', '1123598816738675201');
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225002', '1164733389668962252', '1123598816738675201');
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225003', '1164733389668962253', '1123598816738675201');
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225004', '1164733389668962254', '1123598816738675201');
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225005', '1164733389668962255', '1123598816738675201');
-INSERT INTO `blade_role_menu`(`id`,`menu_id`,`role_id`)
-VALUES ('1161272893875225006', '1164733389668962256', '1123598816738675201');
-
--- ----------------------------
--- 增加岗位类型字典数据
--- ----------------------------
-INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `is_deleted`)
-VALUES (1123598814738777220, 0, 'post_category', '-1', '岗位类型', 12, NULL, 0, 0);
-INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `is_deleted`)
-VALUES (1123598814738777221, 1123598814738777220, 'post_category', '1', '高层', 1, NULL, 0, 0);
-INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `is_deleted`)
-VALUES (1123598814738777222, 1123598814738777220, 'post_category', '2', '中层', 2, NULL, 0, 0);
-INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `is_deleted`)
-VALUES (1123598814738777223, 1123598814738777220, 'post_category', '3', '基层', 3, NULL, 0, 0);
-INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `is_deleted`)
-VALUES (1123598814738777224, 1123598814738777220, 'post_category', '4', '其他', 4, NULL, 0, 0);

+ 27 - 0
doc/sql/update/mysql-update-2.5.0~2.5.1.sql

@@ -0,0 +1,27 @@
+-- ----------------------------
+-- 增加第三方登陆配置
+-- ----------------------------
+UPDATE blade_client set authorized_grant_types = 'refresh_token,password,authorization_code,captcha,social';
+
+
+-- ----------------------------
+-- 创建用户第三方登陆表
+-- ----------------------------
+CREATE TABLE `blade_user_oauth`  (
+ `id` bigint(64) NOT NULL COMMENT '主键',
+ `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '租户ID',
+ `user_id` bigint(64) NULL DEFAULT NULL COMMENT '用户主键',
+ `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号',
+ `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
+ `avatar` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',
+ `blog` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '应用主页',
+ `company` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '公司名',
+ `location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址',
+ `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮件',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `gender` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别',
+ `source` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源',
+ PRIMARY KEY (`id`) USING BTREE
+) COMMENT = '用户第三方认证表' ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 4 - 0
pom.xml

@@ -102,6 +102,10 @@
             <groupId>org.springblade</groupId>
             <artifactId>blade-starter-excel</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-social</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.github.xiaoymin</groupId>
             <artifactId>knife4j-spring-ui</artifactId>

+ 5 - 56
src/main/java/org/springblade/modules/auth/controller/AuthController.java

@@ -16,31 +16,20 @@
  */
 package org.springblade.modules.auth.controller;
 
-import com.github.xiaoymin.knife4j.annotations.ApiSort;
 import com.wf.captcha.SpecCaptcha;
-import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import org.springblade.common.cache.CacheNames;
 import org.springblade.core.cache.constant.CacheConstant;
 import org.springblade.core.cache.utils.CacheUtil;
 import org.springblade.core.launch.constant.AppConstant;
-import org.springblade.core.log.annotation.ApiLog;
 import org.springblade.core.redis.cache.BladeRedis;
-import org.springblade.core.secure.BladeUser;
-import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.support.Kv;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.WebUtil;
-import org.springblade.modules.auth.granter.ITokenGranter;
-import org.springblade.modules.auth.granter.TokenGranterBuilder;
-import org.springblade.modules.auth.granter.TokenParameter;
-import org.springblade.modules.auth.utils.TokenUtil;
-import org.springblade.modules.system.entity.UserInfo;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
 
-import javax.servlet.http.HttpServletResponse;
 import java.time.Duration;
 import java.util.UUID;
 
@@ -49,46 +38,14 @@ import java.util.UUID;
  *
  * @author Chill
  */
-@ApiSort(1)
+@ApiIgnore
 @RestController
 @AllArgsConstructor
 @RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
-@Api(value = "用户授权认证", tags = "授权接口")
 public class AuthController {
 
 	private final BladeRedis bladeRedis;
 
-	@ApiLog("登录用户验证")
-	@PostMapping("/oauth/token")
-	@ApiOperation(value = "获取认证令牌", notes = "传入租户ID:tenantId,账号:account,密码:password")
-	public Kv token(@ApiParam(value = "租户ID", required = true) @RequestParam String tenantId,
-					@ApiParam(value = "账号", required = true) @RequestParam(required = false) String username,
-					@ApiParam(value = "密码", required = true) @RequestParam(required = false) String password) {
-
-		Kv authInfo = Kv.create();
-
-		String grantType = WebUtil.getRequest().getParameter("grant_type");
-		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
-
-		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
-
-		TokenParameter tokenParameter = new TokenParameter();
-		tokenParameter.getArgs().set("tenantId", tenantId).set("username", username).set("password", password).set("grantType", grantType).set("refreshToken", refreshToken).set("userType", userType);
-
-		ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
-		UserInfo userInfo = granter.grant(tokenParameter);
-
-		if (userInfo == null || userInfo.getUser() == null) {
-			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
-		}
-
-		if (Func.isEmpty(userInfo.getRoles())) {
-			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "未获得用户的角色信息");
-		}
-
-		return TokenUtil.createAuthInfo(userInfo);
-	}
-
 	@GetMapping("/oauth/captcha")
 	@ApiOperation(value = "获取验证码")
 	public Kv captcha() {
@@ -101,13 +58,6 @@ public class AuthController {
 		return Kv.create().set("key", key).set("image", specCaptcha.toBase64());
 	}
 
-	@GetMapping("/oauth/logout")
-	@ApiOperation(value = "退出登录")
-	public Kv logout() {
-		BladeUser user = AuthUtil.getUser();
-		return Kv.create().set("success", "true").set("account", user.getAccount()).set("msg", "success");
-	}
-
 	@GetMapping("/oauth/clear-cache")
 	@ApiOperation(value = "清除缓存")
 	public Kv clearCache() {
@@ -121,5 +71,4 @@ public class AuthController {
 		CacheUtil.clear(CacheConstant.PARAM_CACHE);
 		return Kv.create().set("success", "true").set("msg", "success");
 	}
-
 }

+ 95 - 0
src/main/java/org/springblade/modules/auth/endpoint/BladeSocialEndpoint.java

@@ -0,0 +1,95 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.auth.endpoint;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.model.AuthToken;
+import me.zhyd.oauth.request.AuthRequest;
+import me.zhyd.oauth.utils.AuthStateUtils;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.social.props.SocialProperties;
+import org.springblade.core.social.utils.SocialUtil;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 第三方登陆端点
+ *
+ * @author Chill
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
+@ConditionalOnProperty(value = "social.enabled", havingValue = "true")
+@Api(value = "第三方登陆", tags = "第三方登陆端点")
+public class BladeSocialEndpoint {
+
+	private final SocialProperties socialProperties;
+
+	/**
+	 * 授权完毕跳转
+	 */
+	@ApiOperation(value = "授权完毕跳转")
+	@RequestMapping("/oauth/render/{source}")
+	public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
+		AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
+		String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
+		response.sendRedirect(authorizeUrl);
+	}
+
+	/**
+	 * 获取认证信息
+	 */
+	@ApiOperation(value = "获取认证信息")
+	@RequestMapping("/oauth/callback/{source}")
+	public Object login(@PathVariable("source") String source, AuthCallback callback) {
+		AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
+		return authRequest.login(callback);
+	}
+
+	/**
+	 * 撤销授权
+	 */
+	@ApiOperation(value = "撤销授权")
+	@RequestMapping("/oauth/revoke/{source}/{token}")
+	public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) {
+		AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
+		return authRequest.revoke(AuthToken.builder().accessToken(token).build());
+	}
+
+	/**
+	 * 续期accessToken
+	 */
+	@ApiOperation(value = "续期令牌")
+	@RequestMapping("/oauth/refresh/{source}")
+	public Object refreshAuth(@PathVariable("source") String source, String token) {
+		AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
+		return authRequest.refresh(AuthToken.builder().refreshToken(token).build());
+	}
+
+
+}

+ 90 - 0
src/main/java/org/springblade/modules/auth/endpoint/BladeTokenEndPoint.java

@@ -0,0 +1,90 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.auth.endpoint;
+
+import com.github.xiaoymin.knife4j.annotations.ApiSort;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.log.annotation.ApiLog;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.WebUtil;
+import org.springblade.modules.auth.granter.ITokenGranter;
+import org.springblade.modules.auth.granter.TokenGranterBuilder;
+import org.springblade.modules.auth.granter.TokenParameter;
+import org.springblade.modules.auth.utils.TokenUtil;
+import org.springblade.modules.system.entity.UserInfo;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 令牌端点
+ *
+ * @author Chill
+ */
+@ApiSort(1)
+@RestController
+@AllArgsConstructor
+@RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
+@Api(value = "用户授权认证", tags = "授权接口")
+public class BladeTokenEndPoint {
+
+	@ApiLog("登录用户验证")
+	@PostMapping("/oauth/token")
+	@ApiOperation(value = "获取认证令牌", notes = "传入租户ID:tenantId,账号:account,密码:password")
+	public Kv token(@ApiParam(value = "租户ID", required = true) @RequestParam String tenantId,
+					@ApiParam(value = "账号", required = true) @RequestParam(required = false) String username,
+					@ApiParam(value = "密码", required = true) @RequestParam(required = false) String password) {
+
+		Kv authInfo = Kv.create();
+
+		String grantType = WebUtil.getRequest().getParameter("grant_type");
+		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
+
+		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
+
+		TokenParameter tokenParameter = new TokenParameter();
+		tokenParameter.getArgs().set("tenantId", tenantId).set("username", username).set("password", password).set("grantType", grantType).set("refreshToken", refreshToken).set("userType", userType);
+
+		ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
+		UserInfo userInfo = granter.grant(tokenParameter);
+
+		if (userInfo == null || userInfo.getUser() == null) {
+			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
+		}
+
+		if (Func.isEmpty(userInfo.getRoles())) {
+			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "未获得用户的角色信息");
+		}
+
+		return TokenUtil.createAuthInfo(userInfo);
+	}
+
+
+	@GetMapping("/oauth/logout")
+	@ApiOperation(value = "退出登录")
+	public Kv logout() {
+		BladeUser user = AuthUtil.getUser();
+		return Kv.create().set("success", "true").set("account", user.getAccount()).set("msg", "success");
+	}
+}

+ 87 - 0
src/main/java/org/springblade/modules/auth/granter/SocialTokenGranter.java

@@ -0,0 +1,87 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.auth.granter;
+
+import lombok.AllArgsConstructor;
+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 org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.social.props.SocialProperties;
+import org.springblade.core.social.utils.SocialUtil;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.WebUtil;
+import org.springblade.modules.auth.utils.TokenUtil;
+import org.springblade.modules.system.entity.UserInfo;
+import org.springblade.modules.system.entity.UserOauth;
+import org.springblade.modules.system.service.IUserService;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
+
+/**
+ * SocialTokenGranter
+ *
+ * @author Chill
+ */
+@Component
+@AllArgsConstructor
+public class SocialTokenGranter implements ITokenGranter {
+
+	public static final String GRANT_TYPE = "social";
+	private static final Integer AUTH_SUCCESS_CODE = 2000;
+
+	private final IUserService userService;
+	private final SocialProperties socialProperties;
+
+	@Override
+	public UserInfo grant(TokenParameter tokenParameter) {
+		HttpServletRequest request = WebUtil.getRequest();
+		String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
+
+		// 开放平台来源
+		String source = request.getParameter("source");
+		// 开放平台授权码
+		String code = request.getParameter("code");
+		// 开放平台状态吗
+		String state = request.getParameter("state");
+
+		// 获取开放平台授权数据
+		AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
+		AuthCallback authCallback = new AuthCallback();
+		authCallback.setCode(code);
+		authCallback.setState(state);
+		AuthResponse authResponse = authRequest.login(authCallback);
+		AuthUser authUser;
+		if (authResponse.getCode() == AUTH_SUCCESS_CODE) {
+			authUser = (AuthUser) authResponse.getData();
+		} else {
+			throw new ServiceException("social grant failure, auth response is not success");
+		}
+
+		// 组装数据
+		UserOauth userOauth = Objects.requireNonNull(BeanUtil.copy(authUser, UserOauth.class));
+		userOauth.setSource(authUser.getSource());
+		userOauth.setTenantId(tenantId);
+		// 返回UserInfo
+		return userService.userInfo(userOauth);
+	}
+
+}

+ 7 - 6
src/main/java/org/springblade/modules/auth/granter/TokenGranterBuilder.java

@@ -35,12 +35,13 @@ public class TokenGranterBuilder {
 	/**
 	 * TokenGranter缓存池
 	 */
-	private static final Map<String, ITokenGranter> granterPool = new ConcurrentHashMap<>();
+	private static final Map<String, ITokenGranter> GRANTER_POOL = new ConcurrentHashMap<>();
 
 	static {
-		granterPool.put(PasswordTokenGranter.GRANT_TYPE, SpringUtil.getBean(PasswordTokenGranter.class));
-		granterPool.put(CaptchaTokenGranter.GRANT_TYPE, SpringUtil.getBean(CaptchaTokenGranter.class));
-		granterPool.put(RefreshTokenGranter.GRANT_TYPE, SpringUtil.getBean(RefreshTokenGranter.class));
+		GRANTER_POOL.put(PasswordTokenGranter.GRANT_TYPE, SpringUtil.getBean(PasswordTokenGranter.class));
+		GRANTER_POOL.put(CaptchaTokenGranter.GRANT_TYPE, SpringUtil.getBean(CaptchaTokenGranter.class));
+		GRANTER_POOL.put(RefreshTokenGranter.GRANT_TYPE, SpringUtil.getBean(RefreshTokenGranter.class));
+		GRANTER_POOL.put(SocialTokenGranter.GRANT_TYPE, SpringUtil.getBean(SocialTokenGranter.class));
 	}
 
 	/**
@@ -50,11 +51,11 @@ public class TokenGranterBuilder {
 	 * @return ITokenGranter
 	 */
 	public static ITokenGranter getGranter(String grantType) {
-		ITokenGranter tokenGranter = granterPool.get(Func.toStr(grantType, PasswordTokenGranter.GRANT_TYPE));
+		ITokenGranter tokenGranter = GRANTER_POOL.get(Func.toStr(grantType, PasswordTokenGranter.GRANT_TYPE));
 		if (tokenGranter == null) {
 			throw new SecureException("no grantType was found");
 		} else {
-			return granterPool.get(Func.toStr(grantType, PasswordTokenGranter.GRANT_TYPE));
+			return GRANTER_POOL.get(Func.toStr(grantType, PasswordTokenGranter.GRANT_TYPE));
 		}
 	}
 

+ 6 - 0
src/main/java/org/springblade/modules/auth/utils/TokenUtil.java

@@ -73,6 +73,7 @@ public class TokenUtil {
 		param.put(TokenConstant.DEPT_ID, user.getDeptId());
 		param.put(TokenConstant.POST_ID, user.getPostId());
 		param.put(TokenConstant.ROLE_ID, user.getRoleId());
+		param.put(TokenConstant.OAUTH_ID, userInfo.getOauthId());
 		param.put(TokenConstant.ACCOUNT, user.getAccount());
 		param.put(TokenConstant.USER_NAME, user.getAccount());
 		param.put(TokenConstant.NICK_NAME, user.getRealName());
@@ -83,6 +84,11 @@ public class TokenUtil {
 			TokenInfo accessToken = SecureUtil.createJWT(param, "audience", "issuser", TokenConstant.ACCESS_TOKEN);
 			//返回accessToken
 			return authInfo.set(TokenConstant.TENANT_ID, user.getTenantId())
+				.set(TokenConstant.USER_ID, Func.toStr(user.getId()))
+				.set(TokenConstant.DEPT_ID, user.getDeptId())
+				.set(TokenConstant.POST_ID, user.getPostId())
+				.set(TokenConstant.ROLE_ID, user.getRoleId())
+				.set(TokenConstant.OAUTH_ID, userInfo.getOauthId())
 				.set(TokenConstant.ACCOUNT, user.getAccount())
 				.set(TokenConstant.USER_NAME, user.getAccount())
 				.set(TokenConstant.NICK_NAME, user.getRealName())

+ 11 - 0
src/main/java/org/springblade/modules/system/controller/UserController.java

@@ -260,4 +260,15 @@ public class UserController {
 		ExcelUtil.export(response, "用户数据模板", "用户数据表", list, UserExcel.class);
 	}
 
+
+	/**
+	 * 第三方注册用户
+	 */
+	@PostMapping("/register-guest")
+	@ApiOperationSupport(order = 15)
+	@ApiOperation(value = "第三方注册用户", notes = "传入user")
+	public R registerGuest(User user, Long oauthId) {
+		return R.status(userService.registerGuest(user, oauthId));
+	}
+
 }

+ 6 - 0
src/main/java/org/springblade/modules/system/entity/UserInfo.java

@@ -52,4 +52,10 @@ public class UserInfo implements Serializable {
 	@ApiModelProperty(value = "角色集合")
 	private List<String> roles;
 
+	/**
+	 * 第三方授权id
+	 */
+	@ApiModelProperty(value = "第三方授权id")
+	private String oauthId;
+
 }

+ 103 - 0
src/main/java/org/springblade/modules/system/entity/UserOauth.java

@@ -0,0 +1,103 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.system.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 实体类
+ *
+ * @author Chill
+ */
+@Data
+@TableName("blade_user_oauth")
+public class UserOauth implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+
+	/**
+	 * 主键
+	 */
+	@JsonSerialize(using = ToStringSerializer.class)
+	@ApiModelProperty(value = "主键")
+	@TableId(value = "id", type = IdType.ASSIGN_ID)
+	private Long id;
+
+	/**
+	 * 租户ID
+	 */
+	private String tenantId;
+
+	/**
+	 * 用户名
+	 */
+	@JsonSerialize(using = ToStringSerializer.class)
+	@ApiModelProperty(value = "用户主键")
+	private Long userId;
+
+	/**
+	 * 用户名
+	 */
+	private String username;
+	/**
+	 * 用户昵称
+	 */
+	private String nickname;
+	/**
+	 * 用户头像
+	 */
+	private String avatar;
+	/**
+	 * 用户网址
+	 */
+	private String blog;
+	/**
+	 * 所在公司
+	 */
+	private String company;
+	/**
+	 * 位置
+	 */
+	private String location;
+	/**
+	 * 用户邮箱
+	 */
+	private String email;
+	/**
+	 * 用户备注(各平台中的用户个人介绍)
+	 */
+	private String remark;
+	/**
+	 * 性别
+	 */
+	private String gender;
+	/**
+	 * 用户来源
+	 */
+	private String source;
+
+
+}

+ 29 - 0
src/main/java/org/springblade/modules/system/mapper/UserOauthMapper.java

@@ -0,0 +1,29 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.modules.system.entity.UserOauth;
+
+/**
+ * Mapper 接口
+ *
+ * @author Chill
+ */
+public interface UserOauthMapper extends BaseMapper<UserOauth> {
+
+}

+ 22 - 0
src/main/java/org/springblade/modules/system/mapper/UserOauthMapper.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.modules.system.mapper.UserOauthMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="userResultMap" type="org.springblade.modules.system.entity.UserOauth">
+        <result column="id" property="id"/>
+        <result column="tenant_id" property="tenantId"/>
+        <result column="user_id" property="userId"/>
+        <result column="username" property="username"/>
+        <result column="nickname" property="nickname"/>
+        <result column="avatar" property="avatar"/>
+        <result column="blog" property="blog"/>
+        <result column="company" property="company"/>
+        <result column="location" property="location"/>
+        <result column="email" property="email"/>
+        <result column="remark" property="remark"/>
+        <result column="gender" property="gender"/>
+        <result column="source" property="source"/>
+    </resultMap>
+
+</mapper>

+ 30 - 0
src/main/java/org/springblade/modules/system/service/IUserOauthService.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.system.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.modules.system.entity.UserOauth;
+
+/**
+ * 服务类
+ *
+ * @author Chill
+ */
+public interface IUserOauthService extends IService<UserOauth> {
+
+}

+ 19 - 1
src/main/java/org/springblade/modules/system/service/IUserService.java

@@ -20,9 +20,10 @@ package org.springblade.modules.system.service;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.core.mp.base.BaseService;
-import org.springblade.modules.system.excel.UserExcel;
 import org.springblade.modules.system.entity.User;
 import org.springblade.modules.system.entity.UserInfo;
+import org.springblade.modules.system.entity.UserOauth;
+import org.springblade.modules.system.excel.UserExcel;
 
 import java.util.List;
 
@@ -95,6 +96,14 @@ public interface IUserService extends BaseService<User> {
 	 */
 	UserInfo userInfo(String tenantId, String account, String password);
 
+	/**
+	 * 用户信息
+	 *
+	 * @param userOauth
+	 * @return
+	 */
+	UserInfo userInfo(UserOauth userOauth);
+
 	/**
 	 * 给用户设置角色
 	 *
@@ -146,4 +155,13 @@ public interface IUserService extends BaseService<User> {
 	 * @return
 	 */
 	List<UserExcel> exportUser(Wrapper<User> queryWrapper);
+
+	/**
+	 * 注册用户
+	 *
+	 * @param user
+	 * @param oauthId
+	 * @return
+	 */
+	boolean registerGuest(User user, Long oauthId);
 }

+ 36 - 0
src/main/java/org/springblade/modules/system/service/impl/UserOauthServiceImpl.java

@@ -0,0 +1,36 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.system.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.AllArgsConstructor;
+import org.springblade.modules.system.entity.UserOauth;
+import org.springblade.modules.system.mapper.UserOauthMapper;
+import org.springblade.modules.system.service.IUserOauthService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 服务实现类
+ *
+ * @author Chill
+ */
+@Service
+@AllArgsConstructor
+public class UserOauthServiceImpl extends ServiceImpl<UserOauthMapper, UserOauth> implements IUserOauthService {
+
+}

+ 58 - 7
src/main/java/org/springblade/modules/system/service/impl/UserServiceImpl.java

@@ -20,6 +20,7 @@ package org.springblade.modules.system.service.impl;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.exceptions.ApiException;
 import lombok.AllArgsConstructor;
 import org.springblade.common.cache.ParamCache;
 import org.springblade.common.cache.SysCache;
@@ -30,19 +31,15 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.utils.*;
-import org.springblade.modules.system.entity.Tenant;
-import org.springblade.modules.system.entity.User;
-import org.springblade.modules.system.entity.UserDept;
-import org.springblade.modules.system.entity.UserInfo;
+import org.springblade.modules.system.entity.*;
 import org.springblade.modules.system.excel.UserExcel;
 import org.springblade.modules.system.mapper.UserMapper;
-import org.springblade.modules.system.service.IRoleService;
-import org.springblade.modules.system.service.IUserDeptService;
-import org.springblade.modules.system.service.IUserService;
+import org.springblade.modules.system.service.*;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -56,8 +53,10 @@ import static org.springblade.common.constant.CommonConstant.DEFAULT_PARAM_PASSW
 @Service
 @AllArgsConstructor
 public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {
+	private static final String GUEST_NAME = "guest";
 
 	private final IUserDeptService userDeptService;
+	private final IUserOauthService userOauthService;
 	private final IRoleService roleService;
 
 	@Override
@@ -155,6 +154,30 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 		return userInfo;
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public UserInfo userInfo(UserOauth userOauth) {
+		UserOauth uo = userOauthService.getOne(Wrappers.<UserOauth>query().lambda().eq(UserOauth::getSource, userOauth.getSource()).eq(UserOauth::getUsername, userOauth.getUsername()));
+		UserInfo userInfo;
+		if (Func.isNotEmpty(uo) && Func.isNotEmpty(uo.getUserId())) {
+			userInfo = this.userInfo(uo.getUserId());
+			userInfo.setOauthId(Func.toStr(uo.getId()));
+		} else {
+			userInfo = new UserInfo();
+			if (Func.isEmpty(uo)) {
+				userOauthService.save(userOauth);
+				userInfo.setOauthId(Func.toStr(userOauth.getId()));
+			} else {
+				userInfo.setOauthId(Func.toStr(uo.getId()));
+			}
+			User user = new User();
+			user.setAccount(userOauth.getUsername());
+			userInfo.setUser(user);
+			userInfo.setRoles(Collections.singletonList(GUEST_NAME));
+		}
+		return userInfo;
+	}
+
 	@Override
 	public boolean grant(String userIds, String roleIds) {
 		User user = new User();
@@ -233,4 +256,32 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 		return userList;
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public boolean registerGuest(User user, Long oauthId) {
+		Tenant tenant = SysCache.getTenant(user.getTenantId());
+		if (tenant == null || tenant.getId() == null) {
+			throw new ApiException("租户信息错误!");
+		}
+		int userCnt = this.count(Wrappers.<User>query().lambda().eq(User::getTenantId, Func.toStr(user.getTenantId(), BladeConstant.ADMIN_TENANT_ID)).eq(User::getAccount, user.getAccount()));
+		if (userCnt > 0) {
+			throw new ApiException("当前系统用户名已存在!");
+		}
+		UserOauth userOauth = userOauthService.getById(oauthId);
+		if (userOauth == null || userOauth.getId() == null) {
+			throw new ApiException("第三方登陆信息错误!");
+		}
+		user.setRealName(user.getName());
+		user.setAvatar(userOauth.getAvatar());
+		user.setPassword(DigestUtil.encrypt(user.getPassword()));
+		user.setRoleId(StringPool.MINUS_ONE);
+		user.setDeptId(StringPool.MINUS_ONE);
+		user.setPostId(StringPool.MINUS_ONE);
+		boolean userTemp = this.save(user);
+		userOauth.setUserId(user.getId());
+		userOauth.setTenantId(user.getTenantId());
+		boolean oauthTemp = userOauthService.updateById(userOauth);
+		return (userTemp && oauthTemp);
+	}
+
 }

+ 6 - 0
src/main/resources/application-dev.yml

@@ -25,6 +25,11 @@ spring:
     #username: BLADEX_BOOT
     #password: oracle
 
+#第三方登陆
+social:
+  enabled: true
+  domain: http://127.0.0.1:1888
+
 #blade配置
 blade:
   #分布式锁配置
@@ -38,3 +43,4 @@ blade:
     remote-mode: true
     upload-domain: http://localhost:8999
     remote-path: /usr/share/nginx/html
+

+ 5 - 0
src/main/resources/application-prod.yml

@@ -18,6 +18,11 @@ spring:
     username: root
     password: root
 
+#第三方登陆
+social:
+  enabled: true
+  domain: http://127.0.0.1:1888
+
 #blade配置
 blade:
   #分布式锁配置

+ 5 - 0
src/main/resources/application-test.yml

@@ -18,6 +18,11 @@ spring:
     username: root
     password: root
 
+#第三方登陆
+social:
+  enabled: true
+  domain: http://127.0.0.1:1888
+
 #blade配置
 blade:
   #分布式锁配置

+ 26 - 1
src/main/resources/application.yml

@@ -100,14 +100,39 @@ oss:
   secret-key: AuzuA1KHAbkIndCU0dB3Zfii2O3crHNODDmpxHRS
   bucket-name: bladex
 
+#第三方登陆配置
+social:
+  oauth:
+    GITHUB:
+      client-id: 233************
+      client-secret: 233************************************
+      redirect-uri: ${social.domain}/oauth/redirect/github
+    GITEE:
+      client-id: 233************
+      client-secret: 233************************************
+      redirect-uri: ${social.domain}/oauth/redirect/gitee
+    WECHAT_OPEN:
+      client-id: 233************
+      client-secret: 233************************************
+      redirect-uri: ${social.domain}/oauth/redirect/wechat
+    QQ:
+      client-id: 233************
+      client-secret: 233************************************
+      redirect-uri: ${social.domain}/oauth/redirect/qq
+    DINGTALK:
+      client-id: 233************
+      client-secret: 233************************************
+      redirect-uri: ${social.domain}/oauth/redirect/dingtalk
 
 #blade配置
 blade:
+  #xss配置
   xss:
     enabled: true
     skip-url:
       - /blade-chat/weixin
       - /blade-desk/notice/submit
+  #安全框架配置
   secure:
     skip-url:
       - /blade-test/**
@@ -118,10 +143,10 @@ blade:
       - client-id: saber
         path-patterns:
           - /blade-saber/**
+  #多租户配置
   tenant:
     enhance: true
     column: tenant_id
     exclude-tables:
       - blade_user
 
-