關於 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
React中Fetch之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元素,