溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Security框架中怎么使用CorsFilter解決前端跨域請求問題

發(fā)布時間:2021-11-16 10:22:52 來源:億速云 閱讀:190 作者:iii 欄目:開發(fā)技術

本篇內容主要講解“Security框架中怎么使用CorsFilter解決前端跨域請求問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Security框架中怎么使用CorsFilter解決前端跨域請求問題”吧!

項目情況

最近做的pmdb項目是前后端分離的, 由于測試的時候是前端與后端聯(lián)調,所以出現(xiàn)了跨域請求的問題。

瀏覽器默認會向后端發(fā)送一個Options方式的請求,根據(jù)后端的響應來判斷后端支持哪些請求方式,支持才會真正的發(fā)送請求。

CORS介紹

CORS(Cross-Origin Resource Sharing 跨源資源共享),當一個請求url的協(xié)議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。

在日常的項目開發(fā)時會不可避免的需要進行跨域操作,而在實際進行跨域請求時,經(jīng)常會遇到類似 No 'Access-Control-Allow-Origin' header is present on the requested resource.這樣的報錯。

Security框架中怎么使用CorsFilter解決前端跨域請求問題

這樣的錯誤,一般是由于CORS跨域驗證機制設置不正確導致的。

解決方案

注釋:本項目使用的是SprintBoot+Security+JWT+Swagger

第一步

新建CorsFilter,在過濾器中設置相關請求頭

package com.handlecar.basf_pmdb_service.filter; 
import org.springframework.web.filter.OncePerRequestFilter; 
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class CorsFilter extends OncePerRequestFilter { 
//public class CorsFilter implements Filter {
//    static final String ORIGIN = "Origin"; 
    protected void doFilterInternal(
            HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException { 
//        String origin = request.getHeader(ORIGIN); 
        response.setHeader("Access-Control-Allow-Origin", "*");//* or origin as u prefer
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
//        response.setHeader("Access-Control-Allow-Headers", "content-type, authorization");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization");
        response.setHeader("XDomainRequestAllowed","1");
        //使前端能夠獲取到
        response.setHeader("Access-Control-Expose-Headers","download-status,download-filename,download-message");
 
 
        if (request.getMethod().equals("OPTIONS"))
//            response.setStatus(HttpServletResponse.SC_OK);
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        else
            filterChain.doFilter(request, response);
 
    }
 
//    @Override
//    public void doFilter(ServletRequest req, ServletResponse res,
//                         FilterChain chain) throws IOException, ServletException {
//
//        HttpServletResponse response = (HttpServletResponse) res;
//        //測試環(huán)境用【*】匹配,上生產環(huán)境后需要切換為實際的前端請求地址
//        response.setHeader("Access-Control-Allow-Origin", "*");
//        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
//
//        response.setHeader("Access-Control-Max-Age", "0");
//
//        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, auth");
//
//        response.setHeader("Access-Control-Allow-Credentials", "true");
//
//        response.setHeader("XDomainRequestAllowed","1");
//        chain.doFilter(req, res);
//    }
//
//    @Override
//    public void destroy() {
//    }
//
//    @Override
//    public void init(FilterConfig arg0) throws ServletException {
//    }
}

注釋:這里的Access-Control-Expose-Headers的請求頭是為了使前端能夠獲得到后端在response中自定義的header,不設置的話,前端只能看到幾個默認顯示的header。我這里是在使用response導出Excel的時候將文件名和下載狀態(tài)信息以自定義請求頭的形式放在了response的header里。

第二步

在Security的配置文件中初始化CorsFilter的Bean

 @Bean
    public CorsFilter corsFilter() throws Exception {
        return new CorsFilter();
    }
第三步

在Security的配置文件中添加Filter配置,和映射配置

.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
                    // 除上面外的所有請求全部需要鑒權認證。 .and() 相當于標示一個標簽的結束,之前相當于都是一個標簽項下的內容
                .anyRequest().authenticated().and()
                .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)

附:該配置文件

package com.handlecar.basf_pmdb_service.conf;
import com.handlecar.basf_pmdb_service.filter.CorsFilter;
import com.handlecar.basf_pmdb_service.filter.JwtAuthenticationTokenFilter;
import com.handlecar.basf_pmdb_service.security.JwtTokenUtil;
import com.handlecar.basf_pmdb_service.security.CustomAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
//import com.allcom.security.JwtTokenUtil;
 
@Configuration
//@EnableWebSecurity is used to enable Spring Security's web security support and provide the Spring MVC integration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
 
    private final CustomAuthenticationProvider customAuthenticationProvider;
 
    @Autowired
    public WebSecurityConfig(CustomAuthenticationProvider customAuthenticationProvider) {
        this.customAuthenticationProvider = customAuthenticationProvider;
    }
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(customAuthenticationProvider);
    }
 
    @Bean
    public JwtTokenUtil jwtTokenUtil(){
        return new JwtTokenUtil();
    }
 
    @Bean
    public CorsFilter corsFilter() throws Exception {
        return new CorsFilter();
    }
 
    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() {
        return new JwtAuthenticationTokenFilter();
    }
 
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 由于使用的是JWT,我們這里不需要csrf,不用擔心csrf攻擊
                .csrf().disable()
                // 基于token,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 
                .authorizeRequests()
                    //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 
                    // 允許對于網(wǎng)站靜態(tài)資源的無授權訪問
                    .antMatchers(
                        HttpMethod.GET,
                        "/",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/webjars/springfox-swagger-ui/images/**","/swagger-resources/configuration/*","/swagger-resources",//swagger請求
                        "/v2/api-docs"
                    ).permitAll()
                    // 對于獲取token的rest api要允許匿名訪問
                    .antMatchers("/pmdbservice/auth/**","/pmdbservice/keywords/export3").permitAll()
                    .antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
                    // 除上面外的所有請求全部需要鑒權認證。 .and() 相當于標示一個標簽的結束,之前相當于都是一個標簽項下的內容
                .anyRequest().authenticated().and()
                .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
 
        // 禁用緩存
        httpSecurity.headers().cacheControl();
    } 
}

到此,相信大家對“Security框架中怎么使用CorsFilter解決前端跨域請求問題”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI