You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Spring项目中如何为Web URL创建安全短deeplink

核心设计逻辑

要同时满足短链易传播、高安全两个要求,核心是把「短码生成-存储-解析跳转」全链路的风险点堵上,不要留可被利用的漏洞,同时控制短码长度在6-8位,适配短信、公众号等消息渠道的展示要求。

具体实现步骤

1. 短码生成与存储设计

  • 短码不要用纯自增ID转Base62的方案,这种生成的短码是连续的,很容易被人遍历爬取所有有效链接。推荐用雪花算法分布式ID + 安全随机扰动的生成逻辑:取雪花ID的前4位转Base62编码作为基础位,再拼接2-3位由SecureRandom生成的随机字符,最后打乱所有字符顺序,最终生成7位左右的短码即可,单码段可承载百亿级映射,完全够业务使用,且没有连续规律,很难被批量遍历。
  • 存储采用Redis+MySQL双层架构:热点短码映射存在Redis,根据业务场景设置过期时间(比如通知类链接一般设7-30天有效期,到期自动删除),全量映射数据落MySQL持久化,表核心字段只需要存短码、原始目标地址、创建时间、过期时间、绑定用户ID(可选)、风险标记即可,不要冗余无关字段。
  • 注意:不要把原始URL的任何特征编码进短码,避免被反向破解出原始地址规则。

2. 全链路安全防护(核心风险规避)

  • 原始域名白名单校验:所有申请生成短链的原始URL,必须提前在系统配置域名白名单,只允许生成指向自有业务域名的短链,非白名单地址直接拒绝生成,从源头堵死短链被用来跳转钓鱼、违规站点的风险。
  • 接口防爬策略:短链解析接口加IP访问频率限制,单IP1分钟内请求超过阈值(比如20次)直接返回429拦截,避免攻击者批量枚举有效短码。
  • 专属链接权限校验:如果是发送给指定用户的专属链接(比如账单、活动邀请链接),生成短链时绑定目标用户ID,解析时校验当前访问者的登录态/携带的用户凭证,和绑定用户不匹配直接返回403,避免链接泄露后被无关人员访问。
  • 风险熔断机制:建立短链举报、风险标记通道,一旦某条短链被标记为违规,直接在解析层拦截,跳转到内部风险提示页,不再做原始地址跳转。

3. Spring 框架落地核心代码

短码生成工具类示例:

import java.security.SecureRandom;

public class ShortCodeUtil {
    // Base62编码字符集,可去掉容易混淆的l、I、O、0等字符降低用户输入错误率
    private static final String BASE_CHARS = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
    private static final int CODE_LEN = 7;
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();

    public static String genCode() {
        StringBuilder codeBuilder = new StringBuilder();
        // 取雪花ID转Base62的前4位作为基础位
        long snowId = SnowflakeIdWorker.nextId();
        String idSeg = base62Encode(snowId).substring(0, 4);
        codeBuilder.append(idSeg);
        // 拼接3位随机扰动位
        for (int i = 0; i < CODE_LEN - 4; i++) {
            codeBuilder.append(BASE_CHARS.charAt(SECURE_RANDOM.nextInt(BASE_CHARS.length())));
        }
        // 打乱字符顺序,隐藏ID段规律
        return shuffleString(codeBuilder.toString());
    }

    // 省略base62Encode、shuffleString内部实现逻辑
}

短链解析接口示例:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

@RestController
public class DeeplinkResolveController {
    private final ShortLinkService shortLinkService;
    // 构造注入省略

    @GetMapping("/dl/{code}")
    public void resolve(@PathVariable String code, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // IP频率校验
        String clientIp = IpUtil.getClientIp(request);
        if (!rateLimitService.allowAccess(clientIp)) {
            response.setStatus(429);
            return;
        }
        // 查询短链信息
        ShortLinkDO linkInfo = shortLinkService.getByCode(code);
        // 短链不存在或已过期返回404
        if (linkInfo == null || linkInfo.getExpireTime().before(new Date())) {
            response.setStatus(404);
            return;
        }
        // 二次校验目标域名在白名单内
        if (!DomainWhiteListUtil.match(linkInfo.getTargetUrl())) {
            response.setStatus(403);
            return;
        }
        // 专属链接用户身份校验,按需开启
        // if (!userAuthService.checkMatch(linkInfo.getBindUserId(), request)) { response.setStatus(403); return; }
        // 按需加UA判断:移动端访问优先唤起App,实现deeplink能力
        // if (UserAgentUtil.isMobile(request)) { response.sendRedirect(linkInfo.getAppScheme()); return; }
        // 302跳转到目标地址
        response.sendRedirect(linkInfo.getTargetUrl());
    }
}

4. 落地优化建议

  • 短链尽量用独立的短域名,长度越短越好,不要用业务主域名,避免短链出现风险时牵连主域名的信用评级。
  • 所有短链访问日志全量留存,记录访问IP、UA、访问时间,出现安全问题可快速溯源。
  • 非必要不生成永久有效短链,根据业务场景设置合理过期时间,减少存量风险。

内容的提问来源于stack exchange,提问作者AnilF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:15:48