Browse Source

修复跨域配置存在的问题

Jia_RG 6 years ago
parent
commit
d72f83262a

+ 72 - 9
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsAutoConfiguration.java

@@ -1,33 +1,96 @@
 package org.hswebframework.web.starter;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.filter.CorsFilter;
 
+import java.util.Collections;
+import java.util.Optional;
+
 /**
- * 跨域设置
+ * 跨域设置,支持不同的请求路径,配置不同的跨域信息配置
+ *
+ * <p>
+ * Example:
+ * <pre class="code">
+ *   {@code
+ *      hsweb:
+ *        cors:
+ *          enable: true
+ *          configs:
+ *            - /**:
+ *                allowed-headers: "*"
+ *                allowed-methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
+ *                allowed-origins: ["http://xxx.example.com"]
+ *                allow-credentials: true
+ *                maxAge: 1800
+ *   }
+ * </pre>
+ *
+ * enable设为true,但是configs未配置,将使用已下的默认配置:
+ * <pre class="code">
+ *   {@code
+ *      hsweb:
+ *        cors:
+ *          enable: true
+ *          configs:
+ *            - /**:
+ *                allowed-headers: "*"
+ *                allowed-methods: ["GET", "POST", "HEAD"]
+ *                allowed-origins: "*"
+ *                allow-credentials: true
+ *                maxAge: 1800
+ *   }
+ * </pre>
+ *
+ * <p>
+ * <b>注意:</b>
+ * 配置文件中对象的属性名在 SpringBoot 2.x 版本开始不在支持特殊字符,会将特殊字符过滤掉,
+ * 仅支持{@code [A-Za-z0-9\-\_]},具体细节请查看{@code ConfigurationPropertyName}类的{@code adapt}方法
  *
  * @author zhouhao
+ * @author Jia
  * @since 1.0
  */
 @Configuration
 @ConditionalOnProperty(prefix = "hsweb.cors", name = "enable", havingValue = "true")
+@EnableConfigurationProperties(CorsProperties.class)
 public class CorsAutoConfiguration {
 
-    @ConfigurationProperties(prefix = "hsweb.cors")
-    @Bean
-    public CorsConfiguration corsConfiguration() {
-        return new CorsConfiguration();
-    }
+    /**
+     * 默认匹配全部
+     */
+    private static final String CORS_PATH_ALL = "/**";
 
     @Bean
-    public CorsFilter corsFilter(CorsConfiguration corsConfiguration) {
+    public CorsFilter corsFilter(CorsProperties corsProperties) {
         UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
-        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
+
+        Optional.ofNullable(corsProperties.getConfigs())
+                .orElse(Collections.singletonList(Collections.singletonMap(CORS_PATH_ALL,
+                        new CorsProperties.CorsConfiguration().applyPermitDefaultValues())))
+                .forEach((map) ->
+                        map.forEach((path, config) ->
+                                corsConfigurationSource.registerCorsConfiguration(path, buildConfiguration(config))
+                        )
+                );
+
         return new CorsFilter(corsConfigurationSource);
     }
+
+    private CorsConfiguration buildConfiguration(CorsProperties.CorsConfiguration config) {
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.setAllowedHeaders(config.getAllowedHeaders());
+        corsConfiguration.setAllowedMethods(config.getAllowedMethods());
+        corsConfiguration.setAllowedOrigins(config.getAllowedOrigins());
+        corsConfiguration.setAllowCredentials(config.getAllowCredentials());
+        corsConfiguration.setExposedHeaders(config.getExposedHeaders());
+        corsConfiguration.setMaxAge(config.getMaxAge());
+
+        return corsConfiguration;
+    }
 }

+ 85 - 0
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsProperties.java

@@ -0,0 +1,85 @@
+package org.hswebframework.web.starter;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.cors.CorsConfiguration;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+@ConfigurationProperties(prefix = "hsweb.cors"/*, ignoreInvalidFields = true*/)
+public class CorsProperties {
+
+    @Getter
+    @Setter
+    private List<Map<String, CorsConfiguration>> configs;
+
+    @Getter
+    @Setter
+    @ToString
+    public static class CorsConfiguration {
+
+        /**
+         * Wildcard representing <em>all</em> origins, methods, or headers.
+         */
+        public static final String ALL = "*";
+
+        private List<String> allowedOrigins;
+
+        private List<String> allowedMethods;
+
+        private List<String> allowedHeaders;
+
+        private List<String> exposedHeaders;
+
+        private Boolean allowCredentials;
+
+        private Long maxAge;
+
+        CorsConfiguration applyPermitDefaultValues() {
+            if (this.allowedOrigins == null) {
+                this.addAllowedOrigin();
+            }
+            if (this.allowedMethods == null) {
+                this.setAllowedMethods(Arrays.asList(
+                        HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
+            }
+            if (this.allowedHeaders == null) {
+                this.addAllowedHeader();
+            }
+            if (this.allowCredentials == null) {
+                this.setAllowCredentials(true);
+            }
+            if (this.maxAge == null) {
+                this.setMaxAge(1800L);
+            }
+            return this;
+        }
+
+        /**
+         * Add an origin to allow.
+         */
+        void addAllowedOrigin() {
+            if (this.allowedOrigins == null) {
+                this.allowedOrigins = new ArrayList<>(4);
+            }
+            this.allowedOrigins.add(CorsConfiguration.ALL);
+        }
+
+        /**
+         * Add an actual request header to allow.
+         */
+        void addAllowedHeader() {
+            if (this.allowedHeaders == null) {
+                this.allowedHeaders = new ArrayList<>(4);
+            }
+            this.allowedHeaders.add(CorsConfiguration.ALL);
+        }
+    }
+
+}