Spring Security
Spring Security is a security framework that can provide comprehensive secure access control solutions for J2EE projects. It relies on Servlet filters. These filters intercept incoming requests and perform some security processing before the application processes the request.
Spring Security intercepts user requests as follows:
background
In a project that is separated from front and back end, SpringSecurity is used as the security framework, and JWT is used to implement permission management to improve the security of RESTful API. The first thing I encountered was the cross-domain problem, but during the process of carrying the jwt request, the server could not obtain the jwt.
Cross-domain issues
During the development process, I encountered the problem of CORS (cross-domain resource sharing). I simply set up cross-domain access on the server side, but it occurred during the process of carrying jwt request.
Because jwt is placed in the request header, it ignores that cross-domain processing is to add the header field that allows itself to be set to.
@Componentpublic class CorsFilter implements Filter { Logger logger= LoggerFactory.getLogger(CorsFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request= (HttpServletRequest) servletRequest; HttpServletResponse response= (HttpServletResponse) servletResponse; response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin")); response.setHeader("Access-Control-Allow-Origin","*"); //Response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE,PUT"); //The request method allowed to be used response.setHeader("Access-Control-Expose-Headers","*"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Cache-Control,Pragma,Content-Type,Authorization"); //The request method allowed to be used response.setHeader("Access-Control-Allow-Credentials","true"); //The request method allowed to be used response.setHeader("Access-Control-Allow-Credentials","true"); // Whether to allow requests with verification information filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { }} Search online mentioned that it was necessary to process OPTIONS requests and return 200, but the test did not work
The OPTIONS request here is actually a preflight request
Preflight request
But the problem has not been resolved, as follows
Only after Google it is known about the information about the preflight request
When we call the background interface, we often find that we have requested twice. In fact, the first time we send is preflight request (preflight request).
Why you need a preflight request
We all know that the same-origin policy of browsers is that for security reasons, browsers will restrict cross-domain HTTP requests initiated from scripts. XMLHttpRequest and Fetch all follow the same-origin policy.
There are generally two ways for browsers to restrict cross-domain requests:
The browser restricts the issuance of cross-domain requests and cross-domain requests. The cross-domain requests can be initiated normally, but the result returned is intercepted by the browser.
Generally, browsers restrict cross-domain requests in the second way, that is, the request has arrived at the server and may operate on the data in the database. However, the returned result is intercepted by the browser, so we cannot get the return result. This is a failed request, but it may have an impact on the data in the database.
In order to prevent this from happening, the specification requires that for this HTTP request method that may have side effects on the server data, the browser must first use the OPTIONS method to initiate a preflight request to know whether the server allows the cross-domain request: if allowed, send a real request with data; if not allowed, prevent sending a real request with data.
The browser divides CORS requests into two categories: simple requests and non-simple requests.
Simple request
1. The request method is one of the following three methods
2. The header information of HTTP does not exceed the following fields
Anyone who does not meet the above two conditions at the same time is a non-simple request.
The browser handles these two requests differently.
No simple request
A non-simple request is a request that has special requirements for the server, such as the request method is PUT or DELETE, or the type of the Content-Type field is application/json.
A CORS request that is not a simple request will add an HTTP query request before the official communication, which is called a "preflight" request (preflight)
For more detailed reference to cors, please refer to the link at the bottom
Solution
In our background, Spring Security is used as the security framework and no corresponding processing is made to the Preflight request, so this request will cause permission control to fail.
It is also very simple to process. You only need to add a release preflight request to the spring security configuration class configuration method.
@Override protected void configure(HttpSecurity http) throws Exception { http // Since we are using JWT, we do not need csrf .csrf().disable() // Based on token, we do not need session .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() // All requests for / are released.requestMatchers(CorsUtils::isPreFlightRequest).permitAll() //Release preflight.antMatchers("/*").permitAll() .antMatchers("/u").denyAll() .antMatchers("/article/**").permitAll() .antMatchers("/video/**").permitAll() .antMatchers("/api/**").permitAll() .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**","/swagger-ui.html", "/webjars/**") .permitAll() .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**","/swagger-ui.html", "/webjars/**") .permitAll() .antMatchers("/manage/**").hasRole("ADMIN") // Requires a corresponding role to access // All requests except the above require authentication.anyRequest().authenticated(); // Disable cache http.headers().cacheControl(); // Add JWT filter http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); // Add unauthorized processing http.exceptionHandling().authenticationEntryPoint(getAuthenticationEntryPoint()); //Insufficient permissions handle http.exceptionHandling().accessDeniedHandler(getAccessDeniedHandler()); }The problem was finally solved!
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.
refer to:
Front-end | A brief discussion on preflight request
Cross-domain resource sharing CORS detailed explanation