HTML本身不能触发403,必须由服务器或后端框架返回403状态码并响应自定义HTML;直接访问403.html是200,因无权限校验;Nginx需用error_page配合internal防止绕过;Spring Security需配置accessDeniedPage或Controller处理。

直接放结论:HTML 本身不能“做”403权限不足页面,它只是被服务器返回的静态内容;真正的403响应必须由 Web 服务器(如 Nginx、Apache)或后端框架(如 Spring Security、Django)主动触发并返回 403 Forbidden 状态码,再把你的 HTML 文件作为响应体发给浏览器。
为什么直接访问 403.html 会变成 200 而不是 403?
这是最常被误解的一点。如果你把 403.html 放在网站根目录下,然后在浏览器里手动输入 https://yoursite.com/403.html,服务器默认会以 200 OK 返回它——因为这只是普通文件请求,没触发任何权限校验逻辑。
换句话说:403.html 不是“开关”,而是“提示板”。它只在服务器决定拒绝访问时才被亮出来。
- 你访问
/admin,后端检查 session 发现没登录 → 主动返回403+ 渲染403.html - 你请求
/secret/config.json,Nginx 检查到该路径被deny all→ 直接返回403+ 静态403.html - 你直接打开
/403.html→ 服务器当作普通资源返回,状态码是200
Nginx 中怎么让 403 错误显示自定义 HTML 页面?
关键配置项是 error_page,它必须放在 http、server 或 location 块里,且路径要能被 Nginx 读取(注意权限和 root 设置)。
server {
listen 80;
server_name example.com;
root /var/www/html;
<pre class="brush:php;toolbar:false;"># 必须加这一行,否则 403 仍显示默认页
error_page 403 /403.html;
# 确保 /403.html 可被公开访问(不被 deny 拦截)
location = /403.html {
internal; # ← 这行很重要!防止用户直接 GET 它
root /var/www/html;
}
}
注意两个易错点:
-
error_page 403 /403.html中的路径是 URI 路径(以/开头),不是文件系统路径 -
internal表示该 location 只能被 Nginx 内部跳转调用,用户无法直接访问/403.html—— 否则就绕过权限控制了
Spring Security 怎么返回自定义 403 页面?
Spring Boot 项目中,403 通常来自权限校验失败(比如用户没角色却访问了 @PreAuthorize("hasRole('ADMIN')") 接口)。这时不能靠 Nginx,得在 Java 层处理。
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
推荐方式是配置 accessDeniedPage:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedPage("/403.html"); // ← 注意:这个路径要能被 Spring 的静态资源处理器服务
}
同时确保你的 src/main/resources/static/403.html 存在,且没有被其他安全规则拦截(比如别把它写进 .antMatchers("/403.html").denyAll())。
更稳妥的做法是写一个 Controller 返回 403 视图:
@Controller
public class ErrorController {
@GetMapping("/403")
public String accessDenied() {
return "403"; // 对应 templates/403.html(Thymeleaf)或 static/403.html
}
}
然后在 configure() 中用 .accessDeniedHandler(new RedirectAccessDeniedHandler("/403")) 替代 accessDeniedPage。
容易被忽略的细节
真正上线时,这几个点最容易翻车:
- 自定义 403 页面里不要引用
/css/app.css这类相对路径资源——如果当前请求路径是/admin/api/data,浏览器会尝试从/admin/api/css/app.css加载,403 又套 403 - Nginx 的
root和location中的root作用域不同,写错会导致403.html找不到而回退到默认错误页 - 前端路由(如 Vue Router history 模式)下,直接刷新
/admin页面可能触发后端 403,但前端又接管了 URL,导致看不到自定义页——得配合后端 fallback 路由或 Nginx 的try_files
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










