Spring Boot 404错误处理默认行为

huangapple go评论54阅读模式
英文:

Spring boot 404 error handling default behavior

问题

我有一个Spring Boot应用程序,没有对404/500/403等错误进行处理,只是将一些模板放在/resources/templates/error/.html目录下。你可以假设会被具体的错误代码替换,比如404.html。现在我理解Spring Boot足够智能,无需进一步配置就能去获取其中一个模板,这很好。然而,如果你看下面的代码,对于404错误,虽然页面在虚拟服务器和部署服务器上都显示出来,但在部署服务器上不会生成任何thymeleaf变量,即它们都是空的。

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
      layout:decorate="~{layout}">
      <head>
         <title>Error</title>
      </head>
      <body>
       <div layout:fragment="content">
       <div class="container-fluid">
       <div class="header text-center">
        <h3 class="title" id="elementtitle" data-type="text" data-pk="1" data-url="/post">An 
        error occurred</h3>
       </div>
       <div class="row">
       <div class="col-md-6">
       <div class="card">
       <div class="card-header card-header-text card-header-primary">
        <div class="card-text">
          <h4 class="card-title">404 Not Found</h4>
        </div>
       </div>
       <div class="card-body">
         <p>The requested resource could not be found.<a th:href="'hidden for privacy 
        purposes' + ${path}"   title="Error contact">Hidden for privacy purposes</a></p>
          <div class="alert alert-info"> 
             Application: Application<br/>
             Path: [[${path}]]<br/>
             Message: [[${message}]]<br/>
             Previous URL: <data th:text="${#httpServletRequest.getHeader('Referer')}"/> 
              <br/>
             Username: <data sec:authentication="name"/><br/>
             Time: [[${timestamp}]]
          </div>
         </div>
      </div>
     </div>
    </div>
    </div>
    </div>
    </body>
    </html>

正如我已经提到的,所有的thymeleaf变量在部署服务器上都是空的,而在虚拟服务器(localhost)上是正常的。有更多Spring Boot经验的人可以告诉我为什么会出现这种情况吗?我的下一步是实现处理服务器错误的逻辑,但我只是好奇为什么会发生这种情况,因为这不是教程中会出现的情况。

提前感谢您。

英文:

I have a spring boot application with no error handling for 404/500/403 etc just some templates placed in /resources/templates/error/*.html. You can assume that * is replaced with the specific error code such as 404.html. Now to my understanding Spring boot is smart enough to go and grab one of these with no further configuration needed which is great. However, if you look on the code below for 404 while the page is displayed for both the virtual server and the deployed server, on the latter it does not produce any of the thymeleaf variables i.e. they are empty.

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;
  xmlns:layout=&quot;http://www.ultraq.net.nz/thymeleaf/layout&quot;
  xmlns:th=&quot;http://www.thymeleaf.org&quot;
  xmlns:sec=&quot;http://www.thymeleaf.org/extras/spring-security&quot;
  layout:decorate=&quot;~{layout}&quot;&gt;
  &lt;head&gt;
     &lt;title&gt;Error&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
   &lt;div layout:fragment=&quot;content&quot;&gt;
   &lt;div class=&quot;container-fluid&quot;&gt;
   &lt;div class=&quot;header text-center&quot;&gt;
    &lt;h3 class=&quot;title&quot; id=&quot;elementtitle&quot; data-type=&quot;text&quot; data-pk=&quot;1&quot; data-url=&quot;/post&quot;&gt;An 
    error occurred&lt;/h3&gt;
   &lt;/div&gt;
   &lt;div class=&quot;row&quot;&gt;
   &lt;div class=&quot;col-md-6&quot;&gt;
   &lt;div class=&quot;card&quot;&gt;
   &lt;div class=&quot;card-header card-header-text card-header-primary&quot;&gt;
    &lt;div class=&quot;card-text&quot;&gt;
      &lt;h4 class=&quot;card-title&quot;&gt;404 Not Found&lt;/h4&gt;
    &lt;/div&gt;
   &lt;/div&gt;
   &lt;div class=&quot;card-body&quot;&gt;
     &lt;p&gt;The requested resource could not be found.&lt;a th:href=&quot;&#39;hidden for privacy 
    purposes&#39; + ${path}&quot;   title=&quot;Error contact&quot;&gt;Hidden for privacy purposes&lt;/a&gt;&lt;/p&gt;
      &lt;div class=&quot;alert alert-info&quot;&gt; 
         Application: Application&lt;br/&gt;
         Path: [[${path}]]&lt;br/&gt;
         Message: [[${message}]]&lt;br/&gt;
         Previous URL: &lt;data th:text=&quot;${#httpServletRequest.getHeader(&#39;Referer&#39;)}&quot;/&gt; 
          &lt;br/&gt;
         Username: &lt;data sec:authentication=&quot;name&quot;/&gt;&lt;br/&gt;
         Time: [[${timestamp}]]
      &lt;/div&gt;
     &lt;/div&gt;
  &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

As I already mentioned, all the thymeleaf variables are empty on the deployed server while on a virtual server (localhost) is fine. Could anyone with more experience in spring boot let me know why this behavior happens. My next steps are to implement logic to handle the server errors but I was just curious why this happens as it is not something you will find in a tutorial.

Thank you in advance.

答案1

得分: 0

搞定了。显然,Spring Boot 在可部署的远程服务器上出现错误时会清除 SecurityContextHolder 中的 Authentication 对象,以确保安全。因此,如果你需要在捕获 /error 后传播需要用户身份验证的页面,这是默认情况下不可能的。我解决的方法是 1)创建一个持久的 SecurityContextFilter,并为 HttpServletRequest 的 preHandle 和 postHandle 添加拦截器,基本上获取 Authentication 对象,将其存储在请求中的另一个属性中,然后在 ErrorController 中再次获取并设置:

SecurityContextHolder.getContext().setAuthentication(retrievedAuthentication);

这样就可以正常运行。

英文:

Solved it. Apparently Spring boot on a deploy-able remote server clears the Authentication object from the SecurityContextHolder for security purposes when an error occurs, therefore if you need to propagate a page requiring user authentication after capturing /error, it will not be possible by default. What I have done to solve it is 1) make a persistent SecurityContextFilter and added an intercept for preHandle and postHandle of an HttpServletRequest to basically get the Authentication object, store it in another attribute in the request and while in the ErrorController you get it again and set the:

SecurityContextHolder.getContext().setAuthentication(retrievedAuthentication);

and it works like a charm.

huangapple
  • 本文由 发表于 2023年6月5日 18:24:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定