リソース自体が存在するサーバーとは異なるドメインまたはポートからリソースがリクエストされた場合、リソース クロスドメイン HTTP リクエストが開始されます。
セキュリティ上の理由から、ブラウザはスクリプト内から開始されるクロスオリジン HTTP リクエストを制限しています。たとえば、XMLHttpRequest と Fetch API は同じオリジン ポリシーに従います。これは、CORS ヘッダーが使用されない限り、これらの API を使用する Web アプリケーションは、アプリケーションが読み込まれるのと同じドメインからのみ HTTP リソースを要求できることを意味します。
フロントエンドが「Access-Control-Allow-Origin」を要求する場合問題
XMLHttpRequest は http://xxxxxxxxxx/ を読み込めません。いいえ ' Access-Control-Allow-Origin' ヘッダーが要求されたリソースに存在します。Origin 'null' はアクセスを許可されません。
次に、設定する必要があります。クロスドメイン SpringBoot2 フィルターはクロスドメイン アクセスを許可します。
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; @Component public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); chain.doFilter(req, res); } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }
クロスドメイン アドレスを表示する必要がある場合は、トラブルシューティングのためにアクセス元の print ステートメントを追加することもできます。
String curOrigin = request.getHeader("Origin"); System.out.println("###跨域过滤器->当前访问来源->"+curOrigin+"###");
Ifクロスドメイン権限が必要です。ソースは決定できます
String curOrigin = request.getHeader("Origin"); System.out.println("###跨域过滤器->当前访问来源->"+curOrigin+"###"); if(curOrigin.indexOf("127.0.0.1:8080")>-1){ response.setHeader("Access-Control-Allow-Origin", "*"); }
プロトコル、ドメインリクエスト URL の名前とポートが異なる場合、これがクロスドメインです。クロスドメインの問題は、ブラウザーの同一オリジン ポリシーの制限により発生します。
同じオリジン: リクエスト URL のプロトコル、ドメイン名、ポートが同じ場合、同じオリジン (同じドメイン) を意味します。
同一生成元ポリシー: 同一生成元ポリシー (同一生成元ポリシー) は規約であり、ブラウザの中核で最も基本的なセキュリティ機能です。同一オリジン ポリシーは、オリジナル以外のオリジン (同じドメイン) からのコンテンツが相互作用することを防ぎます。
同一オリジンポリシーの制限:
オリジナル以外の Web の Cookie、LocalStorage、IndexedDB を読み取ることができませんページ
オリジナル以外の Web ページの DOM にアクセスできません
ブラウザの同一オリジン ポリシーは、クロスドメイン リクエストを制限します。これを制限するには、通常 2 つの方法があります:
Accept
Accept -Language
単純なクロスドメインリクエストの場合、処理方法は次のとおりです: 1. ブラウザが行う必要があるのは、HTTP リクエストヘッダーに Origin を追加し、 JavaScript スクリプトが配置されているドメインを選択し、それを他のドメインのサーバー要求リソースに追加します。
Origin: http://www.joker.com
Origin フィールドは、このリクエストの送信元 (プロトコル ドメイン名ポート) を示すために使用されます。サーバーは、この値に基づいてリクエストに同意するかどうかを決定します。
2. サーバーは単純なクロスドメイン要求を受信すると、リソースのアクセス許可設定に従って Access-Control-Allow-Origin を応答ヘッダーに追加します。
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。 但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。
如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段:
Access-Control-Allow-Origin: http://www.joker.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: My-Token
Access-Control-Allow-Origin
:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*值,表示接受任意域名的请求。
Access-Control-Allow-Credentials
: 该字段是可选的。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
Access-Control-Expose-Headers
:该字段是可选的。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
3.浏览器收到响应后,通过获取响应头中的Access-Control-Allow-Origin字段,来判断如果当前域已经得到授权,则将结果返回给JavaScript。否则浏览器忽略此次响应。
非简单跨域请求需满足的条件:
除GET、HEAD和POST(Content-Type的值是:application/x-www-form-urlencoded、multipart/form-data、text/plain中的一个值)以外的其他HTTP方法
如:PUT、DELETE、TRACE、PATCH、POST(Content-Type的值是:application/json)。
请求中有自定义HTTP头部。
以上两点只要至少满足其中一点就是非简单跨域请求。
对于非简单跨域请求,处理方式如下:
1.浏览器在发送真实HTTP请求之前先发送一个OPTIONS的预检请求,检测服务器端是否支持真实请求进行跨域资源访问。
真实请求的信息在OPTIONS请求中通过请求头中的Access-Control-Request-Method和Access-Control-Request-Headers字段来描述。此外与简单跨域请求一样,请求头中也会有Origin字段。
Origin: http://www.joker.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Header1,Header2
Origin
:必须字段,用于指定请求源。
Access-Control-Request-Method
:必须字段,用于描述真实请求的方法(PUT、DELETE等)。
Access-Control-Request-Headers
:指定真实请求会额外发送的请求头字段信息。
2.服务器端接到预检请求后,会检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段,检验是否允许跨源请求。
如果不允许该跨域请求,会返回一个正常的HTTP回应,但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。
如果允许该跨域请求,就会在响应头中放入Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,分别表示允许跨域资源请求的域、请求方法和请求头。此外,服务器端还可以在响应头中放入Access-Control-Max-Age,允许浏览器在指定时间内,无需再发送预检请求进行协商,直接用本次协商结果即可。
Access-Control-Allow-Origin: http://www.joker.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Header1,Header2,Header3 Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1728000
Access-Control-Allow-Methods
:该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
Access-Control-Allow-Headers
:如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
Access-Control-Allow-Credentials
: 该字段与简单请求时的含义相同。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
Access-Control-Max-Age
: 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。
浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。这个过程对真实请求的调用者来说是透明的。
SpringBoot设置CORS的的本质都是通过设置响应头信息来告诉前端该请求是否支持跨域。
SpringBoot设置CORS的方式主要有以下三种。
1. 配置过滤器CorsFilter
@Configuration public class CorsConfig { @Bean CorsFilter corsFilter() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return new CorsFilter(source); } }
2. 实现接口WebMvcConfigurer
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedHeaders("*") .allowedMethods("*") .allowCredentials(true); } }
3. 使用注解@CrossOrigin
@CrossOrigin注解可以用在类或者方法上
用在控制器类上,表示 该类的所有方法都允许跨域
@RestController @CrossOrigin public class TestController { @GetMapping("test") public String test() { return "success"; } }
用在控制器方法上,表示该方法都允许跨域
@RestController public class TestController { @CrossOrigin @GetMapping("test") public String test() { return "success"; } }
@CrossOrigin注解源码
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CrossOrigin { /** * 这origins和value是一样的 * 允许来源域名的列表,例如 www.baidu.com,匹配的域名是跨域预请求Response头中的Access-Control-Aloow_origin字段值。 * 不设置确切值时默认支持所有域名跨域访问。 */ @AliasFor("origins") String[] value() default {}; @AliasFor("value") String[] origins() default {}; /** * 高版本下Spring2.4.4使用originPatterns而不是value和origins */ String[] originPatterns() default {}; /** * 跨域请求中允许的请求头中的字段类型, 该值对应跨域预请求Response头中的Access-Control-Allow-Headers字段值。 * 不设置确切值默认支持所有的header字段(Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma)跨域访问 */ String[] allowedHeaders() default {}; /** * 跨域请求请求头中允许携带的除Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma这六个基本字段之外的其他字段信息, * 对应的是跨域请求Response头中的Access-control-Expose-Headers字段值 */ String[] exposedHeaders() default {}; /** * 跨域HTTP请求中支持的HTTP请求类型(GET、POST...), * 不指定确切值时默认与 Controller 方法中的 methods 字段保持一致。 */ RequestMethod[] methods() default {}; /** * 浏览器是否将本域名下的cookie信息携带至跨域服务器中。默认携带至跨域服务器中,但要实现cookie共享还需要前端在AJAX请求中打开withCredentials属性。 * 该值对应的是是跨域请求 Response 头中的 'Access-Control-Allow-Credentials' 字段值。 */ String allowCredentials() default ""; /** * 该值的目的是减少浏览器预检请求/响应交互的数量。默认值1800s。设置了该值后,浏览器将在设置值的时间段内对该跨域请求不再发起预请求。 * 该值对应的是是跨域请求Response头中的Access-Control-Max-Age字段值,表示预检请求响应的缓存持续的最大时间。 */ long maxAge() default -1; }
以上がSpringBoot でクロスドメイン フィルターを構成してクロスドメイン アクセスを許可する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。