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中(前端无法直接读取),可以做两种调整:
- 后端适配:修改接口通过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 }); - 不推荐的方案:将接口改为支持GET请求,但这种方式存在安全风险(GET请求易被缓存、记录),不建议采用。
内容的提问来源于stack exchange,提问作者Stefan Jankovic
相关产品推荐
相关产品推荐

