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
- Add the actual Host value (shown in the error message) to sa-token.firewall.allow-hosts
- Or disable the check: sa-token.firewall.host-check=false when you cannot control incoming Hosts
- 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
- Keep allow-hosts in sync with every domain/CDN/subdomain that fronts the app
- Set proxy_set_header Host correctly on nginx/envoy
- Include localhost and the pod IP if K8s probes pass through the check
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.