文章

登录用户支持多表存储

登录用户支持多表存储

新增 租户客户表

CREATE TABLE `toc_custom` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `username` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
  `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户表';

INSERT INTO `toc_custom`(`id`, `nickname`, `username`, `password`) VALUES (1, 'test', 'test', '123456');

新增 TocCustom 实体

@Data
public class TocCustom implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id;
	private String nickname;
	private String username;
	private String password;
}

新增 TocCustomMapper 查询工具

@Mapper
public interface TocCustomMapper extends BaseMapper<TocCustom> {
}

新增 custom 查询接口

@Inner
@GetMapping("/custom/{username}")
public R customInfo(@PathVariable String username) {
  TocCustom custom = customMapper.selectOne(Wrappers.<TocCustom>lambdaQuery()
      .eq(TocCustom::getUsername, username));
  return R.ok(custom);
}

增加调用 custom 接口

@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.UPMS_SERVICE)
public interface RemoteUserService {
	@GetMapping("/user/custom/{username}")
	R<TocCustom> custom(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM) String from);
}

修改认证中心代码

增加 custom 客户端

INSERT INTO `sys_oauth_client_details` (`id`,`client_id`,`resource_ids`,`client_secret`,`scope`,`authorized_grant_types`,`web_server_redirect_uri`,`authorities`,`access_token_validity`,`refresh_token_validity`,`additional_information`,`autoapprove`) VALUES (20000,'custom',NULL,'custom','server','password,refresh_token',NULL,NULL,10000,11111111,'','true');		

修改整个框架最核心的代码 custom 客户端的专用 UserDetailsService

@Slf4j
@RequiredArgsConstructor
public class JmakeTenantUserDetailsServiceImpl implements JmakeUserDetailsService {

	private final RemoteTenantUserService remoteTenantUserService;

	private final CacheManager cacheManager;

	/**
	 * 用户名密码登录
	 * @param username 用户名
	 * @return
	 */
	@Override
	@SneakyThrows
	public UserDetails loadUserByUsername(String username) {
		Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
		if (cache != null && cache.get(username) != null) {
			return (JmakeUser) cache.get(username).get();
		}

		R<TenantUser> result = remoteTenantUserService.tenantUser(username, SecurityConstants.FROM_IN);
		// 根据 result 构建security 框架需要的 用户对象
		TenantUser custom = result.getData();
		if (custom == null) {
			throw new UsernameNotFoundException("用户不存在");
		}

		JmakeUser jmakeUser = new JmakeUser(custom.getId(), null, custom.getUsername(), "{noop}" + custom.getPassword(),
				null, true, true, true, true, AuthorityUtils.NO_AUTHORITIES);

		if (cache != null) {
			cache.put(username, jmakeUser);
		}

		// 构造security用户
		return jmakeUser;
	}

	/**
	 * 是否支持此客户端校验
	 * @param clientId 目标客户端
	 * @param grantType
	 * @return true/false
	 */
	@Override
	public boolean support(String clientId, String grantType) {
		return "custom".equals(clientId);
	}

	@Override
	public int getOrder() {
		return Integer.MIN_VALUE + 1;
	}

}

配置SPI 加载 CustomUserDetailsService

调用测试

注意需要在网关关闭验证码

# 不校验验证码终端
gateway:
  ignore-clients:
    - test
    - XXX
curl --location --request POST 'http://127.0.0.1:3000/oauth2/token?grant_type=password' \
--header 'Authorization: Basic Y3VzdG9tOmN1c3RvbQ==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=test' \
--data-urlencode 'password=123456' \
--data-urlencode 'scope=server'

License: