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

Spring自定义JWT+Refresh Token登出:页面按钮点击报405错误

问题:Spring JWT登出接口在页面按钮点击时出现405错误

问题描述

我基于Spring实现了JWT+Refresh Token的自定义登出接口,通过Postman测试时功能正常,但在HTML页面添加登出按钮后,点击按钮触发了GET请求,出现405方法不允许错误。

报错信息

There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported

登出接口实现(Java)

@PostMapping("/logout")
public ResponseEntity<?> logout(@RequestBody TokenDTO dto) {
    String refreshTokenString = dto.getRefreshToken();
    if (jwtHelper.validateRefreshToken(refreshTokenString) && refreshTokenRepository.existsById(jwtHelper.getTokenIdFromRefreshToken(refreshTokenString))) {
        // valid and exists in db
        refreshTokenRepository.deleteById(jwtHelper.getTokenIdFromRefreshToken(refreshTokenString));
        return ResponseEntity.ok().build();
    }

    throw new BadCredentialsException("invalid token");
}

原HTML页面代码

<button id="logout" class="float-left submit-button">Log out</button>

<script type="text/javascript">
  document.getElementById("logout").onclick = function () {
    location.href = "http://localhost:8080/api/auth/logout";
  };
</script>

解决方案

问题根源是location.href触发的是GET请求,但你的接口仅支持POST方法。需要修改前端代码,用POST请求调用登出接口,并携带必要的refresh token参数:

修改后的HTML代码

<button id="logout" class="float-left submit-button">Log out</button>

<script type="text/javascript">
document.getElementById("logout").onclick = async function () {
    // 从本地存储取出预先保存的refresh token(根据实际存储方式调整)
    const refreshToken = localStorage.getItem("refreshToken");
    
    if (!refreshToken) {
        alert("无有效刷新令牌");
        return;
    }

    try {
        const response = await fetch("http://localhost:8080/api/auth/logout", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({ refreshToken: refreshToken })
        });

        if (response.ok) {
            // 登出成功后清理本地令牌并跳转登录页
            localStorage.removeItem("accessToken");
            localStorage.removeItem("refreshToken");
            window.location.href = "/login.html";
        } else {
            alert("登出失败");
        }
    } catch (error) {
        console.error("登出请求出错:", error);
        alert("登出请求出错");
    }
};
</script>

补充说明

如果你的refresh token是存在HttpOnly类型的Cookie中(前端无法直接读取),可以做两种调整:

  1. 后端适配:修改接口通过Cookie自动获取refresh token,前端只需发送POST请求并携带Cookie:
    @PostMapping("/logout")
    public ResponseEntity<?> logout(@CookieValue("refreshToken") String refreshTokenString) {
        // 原有业务逻辑不变
    }
    
    对应前端简化请求代码:
    const response = await fetch("http://localhost:8080/api/auth/logout", {
        method: "POST",
        credentials: "include" // 自动携带Cookie
    });
    
  2. 不推荐的方案:将接口改为支持GET请求,但这种方式存在安全风险(GET请求易被缓存、记录),不建议采用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:20:27