18143453325 在线咨询 在线咨询
18143453325 在线咨询
所在位置: 首页 > 营销资讯 > 建站知识 > cname记录是什么?他存在的意义是什么?

cname记录是什么?他存在的意义是什么?

时间:2023-02-26 12:24:01 | 来源:建站知识

时间:2023-02-26 12:24:01 来源:建站知识

cname记录是什么?他存在的意义是什么?:背景

大家在做 SAAS 系统的时候都会遇到这样一个问题,后端是怎么知道用户是通过哪个租户访问的呢?


选择参数传递方式

前端和后端进行参数传递的方式多种多样,应该选择哪种方式和后端传递租户标识呢?
常见的租户标识参数传递方式有:

  1. 通过请求头传递参数
通过请求头传递租户标识是目前比较常见的方式,常见做法是在页面的登录页添加一个租户选择框,前端根据选择的租户标识在请求工具的拦截器统一带给后端。
该方式存在不足:
1.第三方对接支持不好,当该租户的接口需要给第三方做回调的时候就不能支持了,比如微信公众号回调、支付回调等。
2.对租户使用体验不好,需要租户自己在页面手动选择使用的租户,也不方便对登录页进行定制化设计。
  1. 通过 url 传递参数
一般作为通过请求头传递的一个补充,在不支持回调的情况下额外使用。
  1. 通过请求体传递参数
不建议使用,会和业务参数混合在一起,不方便区分。
以上为常见的租户标识传递传递方案,通过请求头 + url 参数配合使用。今天小白给大家分享一个不一样的方案,通过域名 + CNAME 的方式传递租户标识。

域名方式传递租户标识域名配置

首先我们给租户分配一个二级域名作为租户的根域名,比如 http://tenant.xiaobai.com,给域名 http://tenant.xiaobai.com 配置泛解析,*.tenant.xiaobai.com 映射到具体的ip,这样就可以直接通过{租户标识}.tenant.xiaobai.com访问到服务器,但是租户标识往往都是一些没有具体意义的一串字符,比如7e97639a733942c8ba530c5d54857a07,加上大部分的租户都想使用自己的域名,需要增加租户自定义域名,这时候通过租户的域名 CNAME 解析到{租户标识}.tenant.xiaobai.com

关键代码

  1. 编写 CNAME 解析代码工具类DomainTenantParseUtils
/** * 解析域名租户 * * @param domain 当前访问域名 * @param tenantRootDomain 租户的根域名(可以是二级或者三级域名) * @return 租户标识 */ @Nullable public static String parseDomainTenant(@NonNull String domain, @NonNull String tenantRootDomain) { // ip不解析 if (IpUtils.isIP(domain)) { return null; } String resolvingResult; // 当前访问域名在租户根域名下解析结果为当前访问域名 if (domain.endsWith(tenantRootDomain)) { resolvingResult = domain; } else { resolvingResult = getResolvingResult(domain, Type.CNAME); } // 解析结果为空直接返回 if (Objects.isNull(resolvingResult)) { return null; } // 解析结果不在租户根域名下 if (!resolvingResult.endsWith(tenantRootDomain)) { return null; } String[] rootDomainArray = tenantRootDomain.split("//."); String[] resolvingResultArray = resolvingResult.split("//."); // 取租户根域名的下一级 if (resolvingResultArray.length > rootDomainArray.length) { return resolvingResultArray[resolvingResultArray.length - (rootDomainArray.length + 1)]; } return null; } /** * 获取域名解析结果 * * @param domain 域名 * @param type 类型 A记录 或者 CNAME * @see Type */ @Nullable public static String getResolvingResult(String domain, int type) { Resolver resolver; Lookup lookup; try { // 设置DNS服务器,这里使用常用的114.114.114.114 // TODO 这里也可做成配置化 resolver = new SimpleResolver("114.114.114.114"); lookup = new Lookup(domain, type); } catch (TextParseException | UnknownHostException e) { throw new RuntimeException("域名解析异常"); } lookup.setResolver(resolver); org.xbill.DNS.Cache cache = new org.xbill.DNS.Cache(); lookup.setCache(cache); lookup.run(); if (lookup.getResult() == Lookup.SUCCESSFUL) { String[] results = cache.toString().split("//n"); for (String result : results) { String rule = "(?<=//[)(.+?)(?=.])"; Pattern pattern = Pattern.compile(rule); Matcher matcher = pattern.matcher(result); if (matcher.find()) { return matcher.group(); } } } return null; }
  1. 编码全局过滤器TenantParseFilter
@Slf4j@RequiredArgsConstructorpublic class TenantParseFilter extends OncePerRequestFilter { private final TenantProperties tenantProperties; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestServerName = request.getServerName(); String tenant = DomainTenantParseUtils.parseDomainTenant(requestServerName, tenantProperties.getRootDomain()); if (!Objects.isNull(tenant)) { // 获取到了租户标识 if (log.isDebugEnabled()) { log.debug("域名解析到的租户标识:[{}]", tenant); } // TODO 写自己的业务操作,比如设置租户上下文传递 } filterChain.doFilter(request, response); }}

小结

通过域名 + CNAME 的方式传递租户标识可以方便的为每个租户定制不同的域名和登录页而不需要修改任何代码,增加租户的使用体验。

关键词:意义,记录

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭