package com.ruoyi.gateway.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import com.ruoyi.gateway.handler.ValidateCodeHandler; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; /** * 路由配置信息 * * @author ruoyi */ @Configuration public class RouterFunctionConfiguration { /** * 这里为支持的请求头,如果有自定义的header字段请自己添加 */ private static final String ALLOWED_HEADERS = "X-Requested-With, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, request-origin, sign, nonce_str, timestamp, X-Login-Session"; private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD"; private static final String ALLOWED_EXPOSE = "*"; private static final String MAX_AGE = "18000"; @Autowired private ValidateCodeHandler validateCodeHandler; @SuppressWarnings("rawtypes") @Bean public RouterFunction routerFunction() { return RouterFunctions.route( RequestPredicates.GET("/code"), validateCodeHandler); } /** * 跨域配置 */ @Bean public WebFilter corsFilter() { return (ServerWebExchange ctx, WebFilterChain chain) -> { ServerHttpRequest request = ctx.getRequest(); if (CorsUtils.isCorsRequest(request)) { ServerHttpResponse response = ctx.getResponse(); // 所有跨域响应(含预检 OPTIONS)统一在提交前设置 CORS 头 response.beforeCommit(() -> { applyCorsHeaders(request, response); return Mono.empty(); }); if (request.getMethod() == HttpMethod.OPTIONS) { response.setStatusCode(HttpStatus.OK); return Mono.empty(); } } return chain.filter(ctx); }; } private void applyCorsHeaders(ServerHttpRequest request, ServerHttpResponse response) { HttpHeaders headers = response.getHeaders(); String origin = request.getHeaders().getOrigin(); headers.set("Access-Control-Allow-Headers", ALLOWED_HEADERS); headers.set("Access-Control-Allow-Methods", ALLOWED_METHODS); headers.set("Access-Control-Expose-Headers", ALLOWED_EXPOSE); headers.set("Access-Control-Max-Age", MAX_AGE); if (origin != null) { // 反射请求来源,支持携带凭据(Allow-Origin 为 * 时浏览器会拒绝 Allow-Credentials) headers.set("Access-Control-Allow-Origin", origin); headers.set("Access-Control-Allow-Credentials", "true"); headers.set(HttpHeaders.VARY, HttpHeaders.ORIGIN); } else { headers.set("Access-Control-Allow-Origin", "*"); } } }