spring cloud gateway 过滤器配置 跨域配置

  • 过滤器示例: 
package com.ttpark.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ttpark.common.exception.CommonException;
import com.ttpark.common.utils.SecureUtil;
import com.ttpark.common.web.ResponseModel;
import com.ttpark.gateway.enums.ErrorEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
public class AuthVerifyFilter implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(AuthVerifyFilter.class);

    @Autowired
    GatewayFilterConfiguration gatewayFilterConfiguration;
    @Autowired
    private RedisTemplate redisTemplate;

    private static final String oss_cache_prefix = "ONET-OSS-";
    private static final String pda_cache_prefix = "ONET-PDA-";
    private static final String app_cache_prefix = "ONET-APP-";
    private static final Long EXPIRE_TIME = 10000L; //10秒钟

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        logger.info("请求地址:{}", path);
        AuthVerifyExclude authVerifyExclude = gatewayFilterConfiguration.getAuthVerifyExclude(path);
        if (authVerifyExclude != null) { //忽略验证
            logger.info("忽略验证:{}", path);
            if (authVerifyExclude.isGenerateToken()) { //是否生成临时token
                logger.info("生成临时token");
                Integer tenantId = -1;
                if (request.getHeaders().getFirst("tenantId") != null) {
                    tenantId = Integer.parseInt(request.getHeaders().getFirst("tenantId"));
                }
                String token = SecureUtil.getToken(tenantId,-1,"", EXPIRE_TIME); //生成一个临时的token
                ServerHttpRequest host = exchange.getRequest().mutate().header("authKey", token).build();
                ServerWebExchange change = exchange.mutate().request(host).build();
                return chain.filter(change);
            }
            return chain.filter(exchange);
        }
        String authKey = request.getHeaders().getFirst("authKey");
        ServerHttpResponse response = exchange.getResponse();
        if (StringUtils.isEmpty(authKey)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.writeWith(Mono.just(getFailureResponseBody(exchange, ErrorEnum.UNAUTHENTICATED.getValue(), ErrorEnum.UNAUTHENTICATED.getName())));
        }
        try {
            tokenVerify(authKey, path);
            return chain.filter(exchange);
        } catch (Exception e) {
            if (e instanceof CommonException) {
                logger.error("网关检验未通过{}", e.getMessage());
                CommonException ex = (CommonException) e;
                return response.writeWith(Mono.just(getFailureResponseBody(exchange, ex.getCode(), ex.getMessage())));
            }
            logger.error("网关异常", e);
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.writeWith(Mono.just(getFailureResponseBody(exchange, ErrorEnum.UNAUTHORIZED.getValue(), ErrorEnum.UNAUTHORIZED.getName())));
        }
    }

    @Override
    public int getOrder() {
        return -2;
    }


    private DataBuffer getFailureResponseBody(ServerWebExchange exchange, Integer code, String message) {
        ServerHttpResponse response = exchange.getResponse();
        //设置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        return response.bufferFactory().wrap(JSON.toJSONBytes(new ResponseModel(code, message)));
    }

    private void tokenVerify(String authKey, String path) {
        if (StringUtils.isEmpty(path)) {
            return;
        }
        String subject = SecureUtil.getContent(authKey).getSubject();
        JSONObject jsonObject = JSONObject.parseObject(subject);
        int minutes=7*24*60;
        String cacheValueKey = null;
        String cacheKey = null;
        if (path.toLowerCase().contains("onet-oss")) {
            cacheKey = oss_cache_prefix;
            cacheValueKey = "userName";
            minutes=30;
        } else if (path.toLowerCase().contains("onet-app")) {
            cacheKey = app_cache_prefix;
            cacheValueKey = "userId";
        } else if (path.toLowerCase().contains("onet-pda")) {
            cacheKey = pda_cache_prefix;
            cacheValueKey = "userId";
        }
        if (cacheValueKey == null || cacheKey == null) {
            throw new CommonException(ErrorEnum.UNAUTHORIZED.getValue(), ErrorEnum.UNAUTHORIZED.getName());
        }
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        Object token = redisTemplate.opsForValue().get(cacheKey + jsonObject.get(cacheValueKey));
        logger.info("authKey:{},redis-authKey:{}", authKey, token);
        if (token == null) {
            throw new CommonException(ErrorEnum.AUTHKEY.getValue(), ErrorEnum.AUTHKEY.getName());
        }
        if (!authKey.equals(String.valueOf(token))) {
            throw new CommonException(ErrorEnum.OTHER_SPACE_LOGIN.getValue(), ErrorEnum.OTHER_SPACE_LOGIN.getName());
        }
        redisTemplate.opsForValue().set(cacheKey + jsonObject.get(cacheValueKey), token, minutes, TimeUnit.MINUTES);
    }
}

@Component
@ConfigurationProperties(prefix = "spring.cloud.gateway.auth-verify-filter")
class GatewayFilterConfiguration {
    private List excludes = new ArrayList<>();
    private boolean enableSwagger = false;

    public AuthVerifyExclude getAuthVerifyExclude(String path) {
        if (StringUtils.isEmpty(path)) {
            return null;
        }
        if (enableSwagger && (path.toLowerCase().contains("swagger-ui.html")
                || path.toLowerCase().contains("/webjars/springfox-swagger-ui"))
                || path.toLowerCase().contains("/swagger-resources") ||
                path.toLowerCase().contains("/v2/api-docs")) {
            return new AuthVerifyExclude();
        }
        if (excludes == null || excludes.size() == 0) {
            return null;
        }
        for (AuthVerifyExclude authVerifyExclude : excludes) {
            if (path.toLowerCase().contains(authVerifyExclude.getUri().toLowerCase())) {
                return authVerifyExclude;
            }
        }
        return null;
    }

    public List getExcludes() {
        return excludes;
    }

    public void setExcludes(List excludes) {
        this.excludes = excludes;
    }

    public void setEnableSwagger(boolean enableSwagger) {
        this.enableSwagger = enableSwagger;
    }
}

class AuthVerifyExclude {
    private String uri;
    private boolean generateToken = false; //是否生成临时token

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public boolean isGenerateToken() {
        return generateToken;
    }

    public void setGenerateToken(boolean generateToken) {
        this.generateToken = generateToken;
    }
}
  • 跨域请求配置

 

package com.ttpark.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.ttpark.common.web.ResponseModel;
import com.ttpark.gateway.enums.ErrorEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
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.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Set;

@Configuration
public class CorsFilter implements WebFilter {

    @Autowired
    CorsFilterConfiguration corsFilterConfiguration;

    private static final String ALLOWED_EXPOSE = "*";

    @Override
    public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        if (CorsUtils.isCorsRequest(request)) {
            ServerHttpResponse response = exchange.getResponse();
            String origin = request.getHeaders().getFirst(HttpHeaders.ORIGIN);
            if (!allowOrigin(origin)) {
                return response.writeWith(Mono.just(getFailureResponseBody(exchange, 403,
                        "跨域禁止访问")));
            }
            HttpHeaders httpHeaders = response.getHeaders();
            httpHeaders.add("Access-Control-Allow-Headers", corsFilterConfiguration.getAllowHeaders());
            httpHeaders.add("Access-Control-Allow-Methods", corsFilterConfiguration.getMethods());
            httpHeaders.add("Access-Control-Allow-Origin", origin);
            httpHeaders.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
            httpHeaders.add("Access-Control-Max-Age", String.valueOf(corsFilterConfiguration.getMaxAge()));
            httpHeaders.add("Access-Control-Allow-Credentials", String.valueOf(corsFilterConfiguration.getAllowCredentials()));
            if (request.getMethod().name().equals(HttpMethod.OPTIONS.name())) {
                response.setStatusCode(HttpStatus.OK);
                return Mono.empty();
            }
        }
        return chain.filter(exchange);
    }


    boolean allowOrigin(String host) {
        if (StringUtils.isEmpty(host)) {
            return false;
        }
        Set allowOrigins = corsFilterConfiguration.getAllowOrigins();
        if (allowOrigins == null || allowOrigins.size() == 0) {
            return true;
        }
        return allowOrigins.contains(host);
    }

    private DataBuffer getFailureResponseBody(ServerWebExchange exchange, Integer code, String message) {
        ServerHttpResponse response = exchange.getResponse();
        //设置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        return response.bufferFactory().wrap(JSON.toJSONBytes(new ResponseModel(code, message)));
    }
}


@Component
@ConfigurationProperties(prefix = "spring.cloud.gateway.cors-filter")
class CorsFilterConfiguration {
    private String allowHeaders = "x-requested-with, Content-Type, Cache-Control,Authorization, credential, X-XSRF-TOKEN, authKey,tenantId,appType,version";
    private Set allowOrigins;
    private String methods = "*";
    private Long maxAge = 18000L;
    private Boolean allowCredentials = true;

    public String getAllowHeaders() {
        return allowHeaders;
    }

    public void setAllowHeaders(String allowHeaders) {
        this.allowHeaders = allowHeaders;
    }

    public Set getAllowOrigins() {
        return allowOrigins;
    }

    public void setAllowOrigins(Set allowOrigins) {
        this.allowOrigins = allowOrigins;
    }

    public String getMethods() {
        return methods;
    }

    public void setMethods(String methods) {
        this.methods = methods;
    }

    public Long getMaxAge() {
        return maxAge;
    }

    public void setMaxAge(Long maxAge) {
        this.maxAge = maxAge;
    }

    public Boolean getAllowCredentials() {
        return allowCredentials;
    }

    public void setAllowCredentials(Boolean allowCredentials) {
        this.allowCredentials = allowCredentials;
    }
}

 

  • application.yml 配置
server:
  port: 1202
#--------------------------------
spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      auth-verify-filter:
        enableSwagger: true
        excludes:
          - uri: /onet-oss/auth/passwordLogin #这个头部应该添加 tenantId
            generateToken: false #是否生成token
          - uri: /onet-oss/onetBusiness/findOnetBusinessSelect
            generateToken: false
          - uri: /onet-pay/notify/notifyForAliPay
            generateToken: false
          - uri: /onet-pay/notify/notifyForBestPay
            generateToken: false
          - uri: /onet-pay/notify/notifyForWxPay
            generateToken: false
          - uri: /onet-app/appBanner/getStartImage
            generateToken: false
          - uri: /onet-app/login/passwordLogin
            generateToken: false
          - uri: /onet-app/login/smsLogin
            generateToken: false
          - uri: /onet-app/login/getImage
            generateToken: false
          - uri: /onet-app/login/sendLoginSms
            generateToken: false
          - uri: /ttpark-data/device/heart
            generateToken: false
          - uri: /ttpark-data/device/car/in
            generateToken: false
          - uri: /ttpark-data/device/car/out
            generateToken: false
          - uri: /ttpark-data/device/car/update
            generateToken: false
          - uri: /onet-pda/login/passwordLogin
            generateToken: false
          - uri: /onet-pda/login/authKeyLogin
            generateToken: false
      discovery:
        locator:
          enabled: true #是否开启自动发现路由的方式
          lower-case-service-id: true
      #default-filters: #默认header 添加授权信息
        #- AddRequestHeader=authKey, eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJjb21wYW55SWRcIjoyLFwiY29tcGFueU5hbWVcIjpcIuWMl-S6rOeyvuiLsei3r-mAmlwiLFwidGVuYW50SWRcIjoxLFwidXNlck5hbWVcIjpcInBlbmd5b3VcIixcInVzZXJJZFwiOjF9In0.DJbNG5dikpgAZSeunfpRE0tVeWPX4d7OzfsQ9xjlyvqxROGtNYrORM4t1u6lL16YGe8uHZLqvlTD2BOwyNyocA
#-----------------------redis----------------------------
  redis:
    database: 1
    host: 192.168.1.60
    port: 6379
#----------------------------------------------------
eureka:
  client:
    serviceUrl:
      defaultZone: http://192.168.1.22:1001/eureka/
  instance:
    # 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server
    prefer-ip-address: true
#------------------actuator----------------------
management:
  endpoint:
    shutdown:
      enabled: true
    health:
      show-details: always
#---------------------------------------------------
logging:
  level:
    org.springframework.cloud.gateway: debug

 

转载于:https://my.oschina.net/haopeng/blog/3066831

你可能感兴趣的:(spring cloud gateway 过滤器配置 跨域配置)