1. 程式人生 > >關於 Spring Security OAuth2 中 CORS 跨域問題

關於 Spring Security OAuth2 中 CORS 跨域問題

CORS 是一個 W3C 標準,全稱是”跨域資源共享”(Cross-origin resource sharing)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了 AJAX 只能同源使用的限制(跨域資源共享 CORS 詳解)。

解決 CORS 跨域方法大致有如下幾類:

  • 使用 Nginx 代理配置轉發請求。
  • 在 Zuul (配置允許敏感頭資訊等) 或  Spring Cloud Gateway 層配置跨域閘道器路由轉發到資源端不涉及跨域。
  • Spring Boot 資源端配置以支援跨域(適用於無閘道器場景)。

Spring Boot 實現 CORS 跨域 (

官方

  • 單個方法的跨域支援,可以使用 @CrossOrigin 的註解實現
  • 採用 JavaConfig 實現
  • 採用 Filter

但是如果專案中包含 Spring Security 就會有 401 的問題,Spring Security 本身是通過 Filter 實現的,如果沒有對其單獨做 CORS 的處理,在 Web Security 報錯 401 的時候是不會返回相應的 CORS 的欄位的。這會導致出現的 401 錯誤成為了一個無法進行跨域的錯誤,導致前端程式無法正常的處理 401 相應 。對於spring security oauth2 預設介面,例如 /oauth/token 跨域問題,可以通過全域性 CORS Filter 解決。

@Configuration
public class GlobalCorsConfiguration {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader(
"*"); corsConfiguration.addAllowedMethod("*"); // corsConfiguration.addExposedHeader("head1"); //corsConfiguration.addExposedHeader("Location"); UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource); } }

配置 CorsFilter 優先順序與 Spring Security 不攔截 OPTIONS 請求

  • 配置 Spring Security 策略,不攔截 OPTIONS 請求
  • 自定義 CorsFilter,設定 order 優先順序比 Spring Security 的 order 高。

配置伺服器允許 /oauth/token的 OPTIONS 方法,因為 /oauth/token 介面是先發一個 OPTIONS 請求,然後再發送 POST請求,如果是 OPTIONS 介面不被允許,就會返回 401 錯誤。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-1)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.requestMatchers().antMatchers(HttpMethod.OPTIONS, "/oauth/**","/login/**","/logout/**")
//            .and()
//            .authorizeRequests()
//            .antMatchers().permitAll()
//            .and()
//            .formLogin().permitAll(); //新增login form 支援使用者登入及授權

            http.requestMatchers().antMatchers(HttpMethod.OPTIONS, "/oauth/**")
                    .and()
                    .cors()
                    .and()
                    .csrf().disable();
    }
}

再次 Vue(vue-resource) 前端測試呼叫,問題解決。

this.$http.post('http://47.100.188.242:8888/oauth/token',
                        {'grant_type':'password','scope':'read','username':'test','password':'test'}
                        ,{emulateJSON:true,headers:{Authorization: 'Basic Y2ssxpZW50Xzkd5c3VsuX3dlYjpzwZWNyZXRfOTlezdsW5fMTIzNDU2'}}).then(function(){

                }, function(){

                });

報文

OPTIONS http://localhost:8888/oauth/token HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:5000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Thu, 27 Sep 2018 04:38:56 GMT

-------------------------------------------------------------------
POST http://localhost:8888/oauth/token HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Content-Length: 60
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
Origin: http://localhost:5000
Authorization: Basic Y2xpZW50Xzks5c3VuX3dlYjpzZWNyZXRfOsTlzdW5fMTIzNDUs2
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:5000/test.html
Accept-Encoding: gzip, deflate, br

grant_type=password&username=test&password=test&soap=api

HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:5000
Access-Control-Allow-Credentials: true
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Date: Thu, 27 Sep 2018 04:38:56 GMT
Content-Length: 1560

{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJpcnZpbmciLCJzY29wZSI6WyJhbGwiLCJhcGkiLCJ1c2VyIiwicmVhZCIsIndyaXRlIl0sImV4dF9uYW1lIjoiaXJ2aW5nIiwiZXhwIjoxNTM4MDMwMjk4LCJjbGllbnRfbmFtZSI6ImlydmluZyIsImp0aSI6IjIwOTg1ZjJhLWNiMGUtNDRiZi1hZWIyLTYzMGQ5NWFhNDI3ZSIsImNsaWVudF9pZCI6ImNsaWVudF85OXN1bl93ZWIifQ.koBwYKeLGr0KgZkOAN9ENGtKtHyQnzBRR_b0N1Ck1g2hk5VOGKikBTcCf-HBycHDvFZzADyqzi1640JDWo7MwwZm72r4Ih_QN-A_CztAMLyxsMvotMx9Du4z8wOJ4qaOGEuFGj3HFdFaMG3ltaN1WnoxORolFLqd6O-Q21SUhXaOMldOUZ_AyQildNnJ3-EJSavVSEc78jnW0P5fEJtp7QpRTS6nyvwwQifD7uoshnPWWbAeX7rYfAhEie3m7csx6sB_7nnJavKyk_AUpddioOgvw8QDZSmIGPKDeLlFLNpq1NGssgCqECyxdwmWVCs3x7rr6CwRDFfva87moJQAIQ","token_type":"bearer","refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJpcnZpbmciLCJzY29wZSI6WyJhbGwiLCJhcGkiLCJ1c2VyIiwicmVhZCIsIndyaXRlIl0sImF0aSI6IjIwOTg1ZjJhLWNiMGUtNDRiZi1hZWIyLTYzMGQ5NWFhNDI3ZSIsImV4dF9uYW1lIjoiaXJ2aW5nIiwiZXhwIjoxNTM4MDIzMjc1LCJjbGllbnRfbmFtZSI6ImlydmluZyIsImp0aSI6IjRiNTc1MTVlLWEwOTUtNGZiMS05MGQ3LTE0MjQyOTcyMWI1YyIsImNsaWVudF9pZCI6ImNsaWVudF85OXN1bl93ZWIifQ.E8gviZsAb8ci_PMAzj4Oj7bqopr8xNwG3LAwa-pi987yVhg7CTlDhD0QOZLqHVPViwMY7dql-j2ccefwpZsfeaL4i1x5xouANoJ-zRJi7aruxJ_3guy2Ln0fReEYnOnkzKRGjWkdeCbxmrFgg0TkDASB_vTsegsbjqpVfCRg7LAvIcZwQCj1uiSqV8jaHbadvZpA1yZXt7lOMILHwtKkcEOkM7xDUbCHrG1J6qNjRNRbZhI34xXzP0EdXq8_FBA-ykpI1NWTt8jqYtQJfjyZCb9StcQmTqIq234d1ES6uiyZz-pqaiAo7qiVbrK85uOPmuCzuYtZcbWs8neiDeL8_g","expires_in":7161,"scope":"all api user read write","client_name":"irving","ext_name":"irving","jti":"20985f2a-cb0e-44bf-aeb2-630d95aa427e"}

備註:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "docs.spring.io"
            allowedMethods:
            - GET

相關推薦

關於 Spring Security OAuth2 CORS 問題

CORS 是一個 W3C 標準,全稱是”跨域資源共享”(Cross-origin resource sharing)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了 AJAX 只能同源使用的限制(跨域資源共享 CORS 詳解)。 解決 CORS 跨域方法大致有如下幾類: 使用

spring mvc專案配置訪問過濾器

1.在web.xml中配置:<filter> <filter-name>contextFilter</filter-name> <filter-class>xhsoft.fruit.core.filter.WebCon

Spring Security (CORS)資源訪問配置

跨域 class 瀏覽器和服務器 fig w3c xmlhttp nbsp gin ima 1、CORS介紹 CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源(協議 + 域名 + 端口)服務器

spring boot Cors

-a control app ppi map ring als cor spring 在訪問web工程的時候,經常會報一些跨域的錯誤:CORS header ‘Access-Control-Allow-Origin’ missingspring boot中的cors設定方式

CORS 與 TP5的解決方案

在做專案過程中,使用Vue-element-admin作為前端,ThinkPHP5作為後端框架進行開發,會遭遇跨域問題,本文給出ThinkPHP5解決跨域 1.CORS的概念     CORS(Cross-Origin Resource Sharing 跨源資源共享),當

cors請求問題 關於spring -springmvc -mybatis .基於xml配置方式

1:場景還原     今天要寫一個方法, 需求是  在購物車服務上,  呼叫一個個人中心的方法 ,用到了 跨域請求.      我就在個人中心的 上面寫了個方法, 並在springMVC.xml中,配置了    &

Shiro框架在CORS訪問遇到的問題及解決

背景 最近做一個前後端分離的專案時,使用shiro做許可權管理時遇到跨域問題,這裡做一下記錄。   原因 後端通過Shiro配置URL過濾, shiroFilterFactoryBean.setLoginUrl("/unauth"); 預設對於沒有授權的訪問

Spring Boot Web應用開發 CORS 請求設定 Invalid CORS request

使用SpringBoot Web開發程式時,前後端分離時,經常遇到跨域問題,特別是很多情況下Firefox瀏覽器沒有問題,而chrome瀏覽器有問題,僅僅從瀏覽器的web控制檯很難發現有效的錯誤或者告警資訊,因此在開發程式很有必要在開發階段就考慮到並配置好跨域。 SpringBoot

Spring MVC 解決CORS問題

從4.2之後,Spring Framework可以解決跨域問題,開箱即用,下面是從官方文件總結了3種解決辦法。 利用@CrossOrigin註解,作用在Controller的類或方法上,可以指定origins、allowedHeaders、exposedHeaders、all

ReactFetch之cors請求的使用

本篇文章主要介紹了react中fetch之cors跨域請求的實現方法,寫的十分的全面細緻,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。 專案中使用了react,當中需要使用fetch來代替ajax。 由於react的create_reac

Spring Boot Web應用開發 CORS 請求支持:

custom auth explorer itl addall sta padding ... per Spring Boot Web應用開發 CORS 跨域請求支持: 一、Web開發經常會遇到跨域問題,解決方案有:jsonp,iframe,CORS等等CORS與JSON

九、Spring Boot 優雅的實現CORS

前言 我們的springboot 架手架已經包含了mysql,redis,定時任務,郵件服務,簡訊服務,檔案上傳下載,以及docker-compose 構建映象等等。 接下來讓我們解決另一個常見的問題。一般的情況下,都是前後端分離的,我這個架手架的初衷也是前後端進行分離,所以這裡就涉及到一個很嚴重的問題啦,當

OAuth2.0學習(4-1)Spring Security OAuth2.0 - 代碼分析

endpoint manager authent work cor tro 過程 pro efi 1、org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter

spring security oauth2 jwt 認證和資源分離的配置文件(java類配置版)

boot cond lan 資源分離 測試 sql adapter 依賴 註入 最近再學習spring security oauth2。下載了官方的例子sparklr2和tonr2進行學習。但是例子裏包含的東西太多,不知道最簡單最主要的配置有哪些。所以決定自己嘗試搭建簡單版

spring security oauth2.0 實現

規範 ppi basic final pre 代碼 處理 state 三方  oauth應該屬於security的一部分。關於oauth的的相關知識可以查看阮一峰的文章:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.htm

CORS——請求那些事兒

lob 有效期 site cati 項目 light 另一個 send 決定 在日常的項目開發時會不可避免的需要進行跨域操作,而在實際進行跨域請求時,經常會遇到類似 No ‘Access-Control-Allow-Origin‘ header is present on

cors問題

sco vs2015 不能 allow 並不會 name config 狀態 添加 這兩天公司布置一個特別簡單的管理系統,增刪查改四個接口,前端使用技術(html/css/angularjs),後臺(c#/mvc),數據庫(mysql) 前端寫完,後臺寫完,在交互的時候就遇

CORS請求總結

eve log 那種 http lencod pos 方法 ref orm CORS跨域請求分為簡單請求和復雜請求。 1. 簡單請求: 滿足一下兩個條件的請求。 (1) 請求方法是以下三種方法之一: HEAD GET POST (2)HTTP的頭信息不超出以下幾種字段:

CORS資源共享你該知道的事兒

自身 沒有 對象的使用方法 one 一起 接受 gpm spa eat “嘮嗑之前,一些客套話” CORS跨域資源共享,這個話題大家一定不陌生了,吃久了大轉轉公眾號的深度技術好文,也該吃點兒小米粥溜溜胃裏的縫兒了,今天咱們就再好好屢屢CORS跨域資源共享這個話題,大牛怡情

前端-關於CORS的解決方案,面向服務端

red 瀏覽器 環境 和我 methods retrieve name 後臺 一件事 最近自己在寫後臺管理系統的時候,並沒有采用jsp、freemaker、葉子等模板技術,而是由後端提供數據api,前端通過AJAX和JQuery來動態操作頁面上的一些div、table元素,