Almost got into trouble with iOS for an HTTP request problem

The cause of this fight is all attributed to iOS. Why do you say that http requests will not be sent? What nonsense (ps: he should not see...).

Let's talk about another bug we've found in the conflict for a long time. Because this is closely related.

Filters in SpringBoot

The filter should be very common, but your filter really plays the role of interception. Here, even if you play the role of interception, can your filter intercept the specified path? Let's take a look at my original writing first.

Prudent reference:

@WebFilter(filterName = "baseFilter", urlPatterns = "/*")
public class BaseFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {

        System.out.println("baseFilter Intercepted /*");
        
        filterChain.doFilter(req, resp);
    }
}

First of all, if you think it's ok to add @ WebFilter, I'll tell you that your face will hurt very much.

Because this annotation is servlet, you must remember to add @ ServletComponentScan annotation on the startup class, so that the filter will be scanned when the application starts.

We wrote a Controller interface and visited it. We can see that the interceptor did intercept our request.

What you think is what you think

Sometimes our project is too big. I don't know what has been introduced. Sometimes this filter can't be injected. When I see the error in that line, my brain may not react, but the CV method has opened Du Niang and found the cause of the problem. Du Niang said you should add a @ comment comment comment. Then it's really good, and then how does he operate next.

@Component
@WebFilter(filterName = "baseFilter", urlPatterns = "/user/*")
public class BaseFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {

        HttpServletRequest request = (HttpServletRequest) req;

        String url = request.getRequestURL().toString();

        System.out.println(url);
        System.out.println("baseFilter Intercepted /*");
        
        filterChain.doFilter(req, resp);
    }
}

Unfortunately, the @ Component annotation solves the problem, but the specified path intercepted by urlPatterns does not take effect.

Here is a request starting with pub, starting with user intercepted by interceptor, and then as follows:

He actually intercepted all the requests to me, which is not what I thought. How can we solve this problem? Look down, classmate.

How does SpringBoot inject filters

I won't list many injection methods here to avoid confusing you. I'll directly tell you how to inject correctly. I've tested it personally and it's very convenient to manage it.

Filter writing

In addition to the implementation of Filter, do not add anything to the Filter. It is so simple.

public class BaseFilter implements Filter {


    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {

        HttpServletRequest request = (HttpServletRequest) req;

        String url = request.getRequestURL().toString();

        System.out.println(url);
        System.out.println("baseFilter Intercepted /*");
        
        filterChain.doFilter(req, resp);
    }
}

Filter injection

We inject filters directly by configuring classes. In this way, we can see all our filters and filter rules at a glance.

The following parameters are basic configurations and are basically required. Name is the class name of the filter, and the first letter is lowercase. Order is the execution order of the filter. The smaller the number, the earlier it is executed.

In this way, we can configure a complete filter. When you access the / pub interface again, it will not be intercepted by BaseFilter.

It is also recommended that you try to configure it like this in the future.

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<BaseFilter> baseFilter() {
        FilterRegistrationBean<BaseFilter> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new BaseFilter());
        filterBean.setName("baseFilter");
        filterBean.addUrlPatterns("/user/*");
        filterBean.setOrder(1);
        return filterBean;
    }
}

My battle with iOS

Let's read the newspaper first and then talk about how I dumped the pot this time

RequestRejectedException: The request was rejected because the URL was not normalized.

See, the request was rejected because the website is not standard.

I had to say there was a problem with my interface. I wanted to fight back. Seeing that the other party was stronger than me, I thought I'd better catch substantive evidence and dump him.

Since the request URL is incorrect, I guess there is something fishy in the request path. Let's grab the package.

Finally, we got the real evidence under various means. Judges, please see:

His request path: http://127.0.0.1:8080//user/list

There is a double slash in his request path, so he must report an error. It should be noted here that the error is due to the introduction of the Security framework.

Now that the problem has been determined, I must stand up and find him to throw the pot. When he sees this, right? He has nothing to say and can only carry the pot silently.

In this way, I successfully threw the pot again this time.

Solution and reflection

Although the pot is thrown out, the problem still needs to be solved.

In fact, according to normal logic, no matter what we introduce, as long as the request path is correct and no matter how many slashes appear in the path, we should also deal with them well and not affect the user's access. So we can handle it through the filter.

public class UriFormatFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain)
            throws ServletException, IOException {

        // Path isolation symbol
        String separateSymbol = "/";

        String uri = req.getRequestURI();
        StringBuilder newUrl = new StringBuilder();

        String[] split = uri.split(separateSymbol);

        for (String s : split) {
            if (StringUtils.isNotBlank(s)) {
                newUrl.append(separateSymbol).append(s);
            }
        }

        req = new HttpServletRequestWrapper(req) {
            @Override
            public String getRequestURI() {
                return newUrl.toString();
            }
        };
        filterChain.doFilter(req, res);
    }
}

Finally, inject the filter

Why does order write - 100 here? If you write 1, you think it will be executed first. In fact, it is not. Before executing it, some filters of the framework may be executed first. Therefore, for the sake of insurance, we set it to - 100 to ensure that the request comes in first.

@Bean
public FilterRegistrationBean<UriFormatFilter> uriFormatFilter() {
    FilterRegistrationBean<UriFormatFilter> filterBean = new FilterRegistrationBean<>();
    filterBean.setFilter(new UriFormatFilter());
    filterBean.setName("uriFormatFilter");
    filterBean.addUrlPatterns("/*");
    filterBean.setOrder(-100);
    return filterBean;
}

be careful

If you pay attention to Mapper and Service in the filter, there may be problems. The object injected during the call may be null, which involves the loading order of the class. I won't bibi it here. If someone meets it, say again. I've solved it anyway.

Reference article:

https://blog.csdn.net/chenmen...
https://blog.csdn.net//qq_300...

For more highlights, please follow wechat official account: the growth of a programmer

Tags: Java Spring Boot

Posted by Liam-PHP on Fri, 06 May 2022 01:44:08 +0300