Browse Source

新增第三方系统登陆

test
smallchill 5 years ago
parent
commit
d79b01a2dd
  1. 18
      blade-auth/pom.xml
  2. 11
      blade-auth/src/main/java/org/springblade/auth/config/BladeAuthorizationServerConfiguration.java
  3. 6
      blade-auth/src/main/java/org/springblade/auth/config/BladeResourceServerConfiguration.java
  4. 6
      blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java
  5. 125
      blade-auth/src/main/java/org/springblade/auth/granter/SocialTokenGranter.java
  6. 7
      blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetails.java
  7. 3
      blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java
  8. 1
      blade-auth/src/main/java/org/springblade/auth/support/BladeJwtTokenEnhancer.java
  9. 1
      blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java
  10. 6
      blade-auth/src/main/resources/application-dev.yml
  11. 6
      blade-auth/src/main/resources/application-prod.yml
  12. 6
      blade-auth/src/main/resources/application-test.yml
  13. 26
      blade-auth/src/main/resources/application.yml
  14. 4
      blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java
  15. 6
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/UserInfo.java
  16. 104
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/UserOauth.java
  17. 11
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java
  18. 15
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java
  19. 7
      blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java
  20. 14
      blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserOauthMapper.java
  21. 22
      blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserOauthMapper.xml
  22. 30
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/IUserOauthService.java
  23. 18
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/IUserService.java
  24. 36
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserOauthServiceImpl.java
  25. 52
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java
  26. 102
      doc/sql/update/mysql-update-2.4.0~2.5.0.sql
  27. 27
      doc/sql/update/mysql-update-2.5.0~2.5.1.sql

18
blade-auth/pom.xml

@ -42,17 +42,21 @@
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-user-api</artifactId>
<version>${bladex.project.version}</version>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-system-api</artifactId>
<artifactId>blade-starter-social</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-user-api</artifactId>
<version>${bladex.project.version}</version>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
<artifactId>blade-system-api</artifactId>
<version>${bladex.project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
@ -77,6 +81,12 @@
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>

11
blade-auth/src/main/java/org/springblade/auth/config/BladeAuthorizationServerConfiguration.java

@ -20,10 +20,10 @@ import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.auth.constant.AuthConstant;
import org.springblade.auth.granter.BladeTokenGranter;
import org.springblade.auth.props.AuthProperties;
import org.springblade.auth.service.BladeClientDetailsServiceImpl;
import org.springblade.core.redis.cache.BladeRedis;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.system.user.feign.IUserClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
@ -52,7 +52,6 @@ import java.util.List;
@Configuration
@AllArgsConstructor
@EnableAuthorizationServer
@EnableConfigurationProperties(AuthProperties.class)
public class BladeAuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final DataSource dataSource;
@ -69,10 +68,14 @@ public class BladeAuthorizationServerConfiguration extends AuthorizationServerCo
private final BladeRedis bladeRedis;
private final IUserClient userClient;
private final SocialProperties socialProperties;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
//获取自定义tokenGranter
TokenGranter tokenGranter = BladeTokenGranter.getTokenGranter(authenticationManager, endpoints, bladeRedis);
TokenGranter tokenGranter = BladeTokenGranter.getTokenGranter(authenticationManager, endpoints, bladeRedis, userClient, socialProperties);
//配置端点
endpoints.tokenStore(tokenStore)

6
blade-auth/src/main/java/org/springblade/auth/config/BladeResourceServerConfiguration.java

@ -49,10 +49,14 @@ public class BladeResourceServerConfiguration extends ResourceServerConfigurerAd
.authorizeRequests()
.antMatchers(
"/actuator/**",
"/token/**",
"/oauth/captcha",
"/oauth/logout",
"/oauth/clear-cache",
"/oauth/render/**",
"/oauth/callback/**",
"/oauth/revoke/**",
"/oauth/refresh/**",
"/token/**",
"/mobile/**",
"/v2/api-docs",
"/v2/api-docs-ext").permitAll()

6
blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java

@ -17,6 +17,8 @@
package org.springblade.auth.granter;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.system.user.feign.IUserClient;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
@ -36,11 +38,13 @@ public class BladeTokenGranter {
/**
* 自定义tokenGranter
*/
public static TokenGranter getTokenGranter(final AuthenticationManager authenticationManager, final AuthorizationServerEndpointsConfigurer endpoints, BladeRedis bladeRedis) {
public static TokenGranter getTokenGranter(final AuthenticationManager authenticationManager, final AuthorizationServerEndpointsConfigurer endpoints, BladeRedis bladeRedis, IUserClient userClient, SocialProperties socialProperties) {
// 默认tokenGranter集合
List<TokenGranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
// 增加验证码模式
granters.add(new CaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis));
// 增加第三方登陆模式
granters.add(new SocialTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), userClient, socialProperties));
// 组合tokenGranter集合
return new CompositeTokenGranter(granters);
}

125
blade-auth/src/main/java/org/springblade/auth/granter/SocialTokenGranter.java

@ -0,0 +1,125 @@
/*
* 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.auth.granter;
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.auth.constant.AuthConstant;
import org.springblade.auth.service.BladeUserDetails;
import org.springblade.auth.utils.TokenUtil;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.core.social.utils.SocialUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.entity.UserOauth;
import org.springblade.system.user.feign.IUserClient;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
/**
* 第三方登录认证类
*
* @author Chill
*/
public class SocialTokenGranter extends AbstractTokenGranter {
private static final String GRANT_TYPE = "social";
private static final Integer AUTH_SUCCESS_CODE = 2000;
private final IUserClient userClient;
private final SocialProperties socialProperties;
protected SocialTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IUserClient userClient, SocialProperties socialProperties) {
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
this.userClient = userClient;
this.socialProperties = socialProperties;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
// 请求头租户信息
HttpServletRequest request = WebUtil.getRequest();
String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
// 开放平台来源
String source = parameters.get("source");
// 开放平台授权码
String code = parameters.get("code");
// 开放平台状态吗
String state = parameters.get("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 InvalidGrantException("social grant failure, auth response is not success");
}
// 组装数据
UserOauth userOauth = Objects.requireNonNull(BeanUtil.copy(authUser, UserOauth.class));
userOauth.setSource(authUser.getSource());
userOauth.setTenantId(tenantId);
// 远程调用,获取认证信息
R<UserInfo> result = userClient.userAuthInfo(userOauth);
BladeUserDetails bladeUserDetails;
if (result.isSuccess()) {
User user = result.getData().getUser();
if (user == null) {
throw new InvalidGrantException("social grant failure, user is null");
}
bladeUserDetails = new BladeUserDetails(user.getId(),
tenantId, result.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(userOauth.getAvatar(), TokenUtil.DEFAULT_AVATAR),
userOauth.getUsername(), AuthConstant.ENCRYPT + user.getPassword(), true, true, true, true,
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())));
} else {
throw new InvalidGrantException("social grant failure, feign client return error");
}
// 组装认证数据,关闭密码校验
Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
// 返回 OAuth2Authentication
return new OAuth2Authentication(storedOAuth2Request, userAuth);
}
}

7
blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetails.java

@ -38,6 +38,10 @@ public class BladeUserDetails extends User {
* 租户ID
*/
private final String tenantId;
/**
* 第三方认证ID
*/
private String oauthId;
/**
* 昵称
*/
@ -71,10 +75,11 @@ public class BladeUserDetails extends User {
*/
private final String avatar;
public BladeUserDetails(Long userId, String tenantId, String name, String realName, String deptId, String postId, String roleId, String roleName, String avatar, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
public BladeUserDetails(Long userId, String tenantId, String oauthId, String name, String realName, String deptId, String postId, String roleId, String roleName, String avatar, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.userId = userId;
this.tenantId = tenantId;
this.oauthId = oauthId;
this.name = name;
this.realName = realName;
this.account = username;

3
blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java

@ -24,6 +24,7 @@ import org.springblade.auth.enums.BladeUserEnum;
import org.springblade.auth.utils.TokenUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.system.entity.Tenant;
@ -98,7 +99,7 @@ public class BladeUserDetailsServiceImpl implements UserDetailsService {
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_ROLE);
}
return new BladeUserDetails(user.getId(),
user.getTenantId(), user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(),user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR),
user.getTenantId(), StringPool.EMPTY, user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR),
username, AuthConstant.ENCRYPT + user.getPassword(), true, true, true, true,
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())));
} else {

1
blade-auth/src/main/java/org/springblade/auth/support/BladeJwtTokenEnhancer.java

@ -43,6 +43,7 @@ public class BladeJwtTokenEnhancer implements TokenEnhancer {
info.put(TokenUtil.POST_ID, Func.toStr(principal.getPostId()));
info.put(TokenUtil.ROLE_ID, Func.toStr(principal.getRoleId()));
info.put(TokenUtil.TENANT_ID, principal.getTenantId());
info.put(TokenUtil.OAUTH_ID, principal.getOauthId());
info.put(TokenUtil.ACCOUNT, principal.getAccount());
info.put(TokenUtil.USER_NAME, principal.getUsername());
info.put(TokenUtil.NICK_NAME, principal.getName());

1
blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java

@ -47,6 +47,7 @@ public class TokenUtil {
public final static String ROLE_ID = TokenConstant.ROLE_ID;
public final static String ROLE_NAME = TokenConstant.ROLE_NAME;
public final static String TENANT_ID = TokenConstant.TENANT_ID;
public final static String OAUTH_ID = TokenConstant.OAUTH_ID;
public final static String CLIENT_ID = TokenConstant.CLIENT_ID;
public final static String LICENSE = TokenConstant.LICENSE;
public final static String LICENSE_NAME = TokenConstant.LICENSE_NAME;

6
blade-auth/src/main/resources/application-dev.yml

@ -8,3 +8,9 @@ spring:
url: ${blade.datasource.dev.url}
username: ${blade.datasource.dev.username}
password: ${blade.datasource.dev.password}
#第三方登陆
blade:
social:
enabled: true
domain: http://127.0.0.1:1888

6
blade-auth/src/main/resources/application-prod.yml

@ -8,3 +8,9 @@ spring:
url: ${blade.datasource.prod.url}
username: ${blade.datasource.prod.username}
password: ${blade.datasource.prod.password}
#第三方登陆
blade:
social:
enabled: true
domain: http://127.0.0.1:1888

6
blade-auth/src/main/resources/application-test.yml

@ -8,3 +8,9 @@ spring:
url: ${blade.datasource.test.url}
username: ${blade.datasource.test.username}
password: ${blade.datasource.test.password}
#第三方登陆
blade:
social:
enabled: true
domain: http://127.0.0.1:1888

26
blade-auth/src/main/resources/application.yml

@ -19,7 +19,33 @@ spring:
connection-test-query: select 1
#connection-test-query: select 1 from dual
#swagger文档
swagger:
base-packages:
- org.springblade
- org.springframework.security.oauth2.provider.endpoint
#第三方登陆
blade:
social:
oauth:
GITHUB:
client-id: 233************
client-secret: 233************************************
redirect-uri: ${blade.social.domain}/oauth/redirect/github
GITEE:
client-id: 233************
client-secret: 233************************************
redirect-uri: ${blade.social.domain}/oauth/redirect/gitee
WECHAT_OPEN:
client-id: 233************
client-secret: 233************************************
redirect-uri: ${blade.social.domain}/oauth/redirect/wechat
QQ:
client-id: 233************
client-secret: 233************************************
redirect-uri: ${blade.social.domain}/oauth/redirect/qq
DINGTALK:
client-id: 233************
client-secret: 233************************************
redirect-uri: ${blade.social.domain}/oauth/redirect/dingtalk

4
blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java

@ -39,6 +39,10 @@ public class AuthProvider {
DEFAULT_SKIP_URL.add("/oauth/captcha/**");
DEFAULT_SKIP_URL.add("/oauth/clear-cache/**");
DEFAULT_SKIP_URL.add("/oauth/user-info");
DEFAULT_SKIP_URL.add("/oauth/render");
DEFAULT_SKIP_URL.add("/oauth/callback");
DEFAULT_SKIP_URL.add("/oauth/revoke");
DEFAULT_SKIP_URL.add("/oauth/refresh");
DEFAULT_SKIP_URL.add("/token/**");
DEFAULT_SKIP_URL.add("/actuator/health/**");
DEFAULT_SKIP_URL.add("/v2/api-docs/**");

6
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/UserInfo.java

@ -34,6 +34,12 @@ public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 第三方授权id
*/
@ApiModelProperty(value = "第三方授权id")
private String oauthId;
/**
* 用户基础信息
*/

104
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/UserOauth.java

@ -0,0 +1,104 @@
/*
* 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.system.user.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.ID_WORKER)
private Long id;
/**
* 租户ID
*/
private String tenantId;
/**
* 用户名
*/
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.ID_WORKER)
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;
}

11
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java

@ -21,6 +21,7 @@ import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.tool.api.R;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.entity.UserOauth;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -41,6 +42,7 @@ public interface IUserClient {
String USER_INFO = API_PREFIX + "/user-info";
String USER_INFO_BY_ID = API_PREFIX + "/user-info-by-id";
String USER_INFO_BY_ACCOUNT = API_PREFIX + "/user-info-by-account";
String USER_AUTH_INFO = API_PREFIX + "/user-auth-info";
String SAVE_USER = API_PREFIX + "/save-user";
String REMOVE_USER = API_PREFIX + "/remove-user";
@ -74,6 +76,15 @@ public interface IUserClient {
@GetMapping(USER_INFO)
R<UserInfo> userInfo(@RequestParam("tenantId") String tenantId, @RequestParam("account") String account);
/**
* 获取第三方平台信息
*
* @param userOauth 第三方授权用户信息
* @return UserInfo
*/
@PostMapping(USER_AUTH_INFO)
R<UserInfo> userAuthInfo(@RequestBody UserOauth userOauth);
/**
* 新建用户
*

15
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@ -82,7 +82,7 @@ public class UserController {
/**
* 查询单条
*/
@ApiOperationSupport(order =2)
@ApiOperationSupport(order = 2)
@ApiOperation(value = "查看详情", notes = "传入id")
@GetMapping("/info")
public R<UserVO> info(BladeUser user) {
@ -236,7 +236,7 @@ public class UserController {
@ApiOperation(value = "导出用户", notes = "传入user")
public void exportUser(@ApiIgnore @RequestParam Map<String, Object> user, BladeUser bladeUser, HttpServletResponse response) {
QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
if (!AuthUtil.isAdministrator()){
if (!AuthUtil.isAdministrator()) {
queryWrapper.lambda().eq(User::getTenantId, bladeUser.getTenantId());
}
queryWrapper.lambda().eq(User::getIsDeleted, BladeConstant.DB_NOT_DELETED);
@ -255,4 +255,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));
}
}

7
blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java

@ -22,6 +22,7 @@ import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.entity.UserOauth;
import org.springblade.system.user.service.IUserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -57,6 +58,12 @@ public class UserClient implements IUserClient {
return R.data(service.userInfo(tenantId, account));
}
@Override
@PostMapping(USER_AUTH_INFO)
public R<UserInfo> userAuthInfo(@RequestBody UserOauth userOauth) {
return R.data(service.userInfo(userOauth));
}
@Override
@PostMapping(SAVE_USER)
public R<Boolean> saveUser(@RequestBody User user) {

14
blade-auth/src/main/java/org/springblade/auth/props/AuthProperties.java → blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserOauthMapper.java

@ -14,20 +14,16 @@
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.auth.props;
package org.springblade.system.user.mapper;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.system.user.entity.UserOauth;
/**
* AuthProperties
* Mapper 接口
*
* @author Chill
*/
@Data
@RefreshScope
@ConfigurationProperties(prefix = "blade.oauth")
public class AuthProperties {
public interface UserOauthMapper extends BaseMapper<UserOauth> {
}

22
blade-service/blade-user/src/main/java/org/springblade/system/user/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.system.user.mapper.UserOauthMapper">
<!-- 通用查询映射结果 -->
<resultMap id="userResultMap" type="org.springblade.system.user.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
blade-service/blade-user/src/main/java/org/springblade/system/user/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.system.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.system.user.entity.UserOauth;
/**
* 服务类
*
* @author Chill
*/
public interface IUserOauthService extends IService<UserOauth> {
}

18
blade-service/blade-user/src/main/java/org/springblade/system/user/service/IUserService.java

@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.entity.UserOauth;
import org.springblade.system.user.excel.UserExcel;
import java.util.List;
@ -77,6 +78,14 @@ public interface IUserService extends BaseService<User> {
*/
UserInfo userInfo(String tenantId, String account);
/**
* 用户信息
*
* @param userOauth
* @return
*/
UserInfo userInfo(UserOauth userOauth);
/**
* 根据账号获取用户
*
@ -137,4 +146,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
blade-service/blade-user/src/main/java/org/springblade/system/user/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.system.user.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springblade.system.user.entity.UserOauth;
import org.springblade.system.user.mapper.UserOauthMapper;
import org.springblade.system.user.service.IUserOauthService;
import org.springframework.stereotype.Service;
/**
* 服务实现类
*
* @author Chill
*/
@Service
@AllArgsConstructor
public class UserOauthServiceImpl extends ServiceImpl<UserOauthMapper, UserOauth> implements IUserOauthService {
}

52
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@ -20,6 +20,7 @@ package org.springblade.system.user.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.constant.CommonConstant;
import org.springblade.core.log.exception.ServiceException;
@ -36,14 +37,17 @@ import org.springblade.system.user.cache.UserCache;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.entity.UserDept;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.entity.UserOauth;
import org.springblade.system.user.excel.UserExcel;
import org.springblade.system.user.mapper.UserMapper;
import org.springblade.system.user.service.IUserDeptService;
import org.springblade.system.user.service.IUserOauthService;
import org.springblade.system.user.service.IUserService;
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;
@ -57,8 +61,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 ISysClient sysClient;
@Override
@ -147,6 +153,31 @@ 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())) {
User user = this.getById(uo.getUserId());
userInfo = this.userInfo(user.getTenantId(), user.getAccount());
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();
@ -225,4 +256,25 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
return userList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean registerGuest(User user, Long oauthId) {
R<Tenant> tenant = sysClient.getTenant(user.getTenantId());
if (!tenant.isSuccess() || tenant.getData().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("当前系统用户名已存在!");
}
user.setTenantId(AuthUtil.getTenantId());
user.setRealName(user.getName());
boolean userTemp = this.save(user);
UserOauth uo = new UserOauth();
uo.setId(oauthId);
uo.setUserId(user.getId());
boolean oauthTemp = userOauthService.updateById(uo);
return (userTemp && oauthTemp);
}
}

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
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;
Loading…
Cancel
Save