dromara/Sa-Token · error · FirewallCheckException

非法请求 host:{host}

Error message

非法请求 host:{host}

What it means

When sa-token.firewall.check-host is enabled, the Host firewall hook reads the request's Host (req.getHost()) and requires it to be matched by one of the configured allowHosts patterns via SaStrategy.hasElement. A mismatch throws FirewallCheckException with the actual host value in the message. This defends against Host-header poisoning attacks.

Source

Thrown at sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java:73

    public void resetConfig(boolean isCheckHost, String... allowHosts) {
        this.isCheckHost = isCheckHost;
        this.allowHosts.clear();
        this.allowHosts.addAll(Arrays.asList(allowHosts));
    }

    /**
     * 执行的方法
     *
     * @param req 请求对象
     * @param res 响应对象
     * @param extArg 预留扩展参数
     */
    @Override
    public void execute(SaRequest req, SaResponse res, Object extArg) {
        if(isCheckHost) {
            String host = req.getHost();
            if( ! SaStrategy.instance.hasElement.apply(allowHosts, host) ) {
                throw new FirewallCheckException("非法请求 host:" + host);
            }
        }
    }

}

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Add the actual Host value (shown in the error message) to sa-token.firewall.allow-hosts
  2. Or disable the check: sa-token.firewall.host-check=false when you cannot control incoming Hosts
  3. Configure nginx proxy_set_header Host $host; so the upstream sees the intended public host

Example fix

# before
sa-token:
  firewall:
    host-check: true
    allow-hosts: [example.com]
# request with Host: api.example.com -> blocked

# after
sa-token:
  firewall:
    host-check: true
    allow-hosts: [example.com, api.example.com]
Defensive patterns

Strategy: validation

Validate before calling

boolean check = SaManager.getConfig().getFirewall().getIsCheckHost();
if (check) {
    String host = req.getHost();
    boolean ok = SaStrategy.instance.hasElement.apply(
        SaManager.getConfig().getFirewall().getAllowHosts(), host);
    if (!ok) { /* reject with 400 before firewall hook */ }
}

Try / catch

try {
    chain.doFilter(req, res);
} catch (FirewallCheckException e) {
    res.setStatus(400); // Host not allowed
}

Prevention

When it happens

Trigger: Enabling firewall.host-check=true but accessing the app via an IP address, a container hostname, an internal domain, or a port-suffixed Host that is not in allow-hosts; also forged Host headers from attackers.

Common situations: Deploying behind a new domain/CDN without updating allow-hosts; Docker/K8s health checks hitting the pod IP so Host is '10.x.x.x'; local testing with localhost while only the production domain is whitelisted; proxy not rewriting the Host header.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/b4d7aa042a7fd32e. Report an issue: GitHub.