protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
            throws ServletException, IOException {

        Throwable t = null;

        try {
            final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
            final ServletResponse response = prepareServletResponse(request, servletResponse, chain);

            final Subject subject = createSubject(request, response);

            subject.execute((Callable<Void>) () -> {
                updateSessionLastAccessTime(request, response);
                executeChain(request, response, chain);
                return null;
            });
        } catch (ExecutionException ex) {
            t = ex.getCause();
        } catch (Throwable throwable) {
            t = throwable;
        }

        if (t != null) {
            if (t instanceof ServletException) {
                throw (ServletException) t;
            }
            if (t instanceof IOException) {
                throw (IOException) t;
            }
            //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
            String msg = "Filtered request failed.";
            throw new ServletException(msg, t);
        }
    }
{@code doFilterInternal} implementation that sets-up, executes, and cleans-up a Shiro-filtered request.  It
performs the following ordered operations:
<ol>
<li>{@link #prepareServletRequest(ServletRequest, ServletResponse, FilterChain) Prepares}
the incoming {@code ServletRequest} for use during Shiro's processing</li>
<li>{@link #prepareServletResponse(ServletRequest, ServletResponse, FilterChain) Prepares}
the outgoing {@code ServletResponse} for use during Shiro's processing</li>
<li> {@link #createSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) Creates} a
{@link Subject} instance based on the specified request/response pair.</li>
<li>Finally {@link Subject#execute(Runnable) executes} the
{@link #updateSessionLastAccessTime(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} and
{@link #executeChain(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)}
methods</li>
</ol>
<p/>
The {@code Subject.}{@link Subject#execute(Runnable) execute(Runnable)} call in step #4 is used as an
implementation technique to guarantee proper thread binding and restoration is completed successfully.

@param servletRequest  the incoming {@code ServletRequest}
@param servletResponse the outgoing {@code ServletResponse}
@param chain           the container-provided {@code FilterChain} to execute
@throws IOException                    if an IO error occurs
@throws javax.servlet.ServletException if a Throwable other than an IOException
web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java