欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微服务-springcloud-zuul

程序员文章站 2022-03-03 20:41:55
...

#zuul的作用

1、进行认证处理:可以对发送过来的请求做认证处理
2、审查与监控:可以记录各个请求的响应信息,将异常或者错误信息存入到数据库中,然后对数据库的数据进行处理
3、动态路由:根据配置将请求发送到指定的服务中去
4、负载均衡:与eureka配合使用,根据注册的多个service-id(Application),实现负载均衡
5、压力测试:根据动态路由的特点可以对某一个服务进行加大访问量的处理,实现压力测试
当不进行路由配置的时候直接可以使用zuul服务+service-id+访问路径对服务进行访问

#配置zuul
##配置跨域问题

@Configuration
public class CorsFilterConfig {
    @Bean
    public CorsFilter corsConfig() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(18000L);
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

##配置filter
###权限过滤器

package com.sgcc.zuul.filter;

import com.google.gson.Gson;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.config.TokenProperties;
import com.sgcc.zuul.model.ResultVO;
import com.sgcc.comm.util.CookieUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

@Slf4j
@Component
public class AuthFilter extends ZuulFilter {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    private TokenProperties tokenProperties;
    //无权限时的提示语
    private static final String INVALID_TOKEN = "invalid token";

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        log.info("网关前置过滤器========》》》uri={}", request.getRequestURI());
        if ("false".equals(tokenProperties.getFilterSwitch()) || tokenProperties.getWhiteList().contains(request.getRequestURI())) {
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        checkToken(requestContext, request);
        return null;
    }

    /**
     * 校验token
     *
     * @param requestContext
     * @param request
     */
    private void checkToken(RequestContext requestContext, HttpServletRequest request) {
        //先从 cookie 中取 token,cookie 中取失败再从 header 中取,两重校验
        String token = getToken(request);
        //如果获取的token为空,则直接返回401无权限
        if (StringUtils.isEmpty(token)) {
            setUnauthorizedResponse(requestContext, INVALID_TOKEN);
        } else {
            String value = stringRedisTemplate.opsForValue().get(token);
            if (StringUtils.isEmpty(value)) {
                setUnauthorizedResponse(requestContext, INVALID_TOKEN);
            } else {
                String[] values = value.split("_");
                String checkToken = values[0];
                String userId = values[1];
                log.info("当前正在操作的用户ID为userId={}", userId);
            }
        }
    }

    /**
     * 获取token
     *
     * @return
     */
    private String getToken(HttpServletRequest request) {
        String token = CookieUtil.getValue(request, "X-Token");//先从cookie获取
        if (StringUtils.isEmpty(token)) {//如果cookie获取的token为空
            token = request.getHeader("X-Token");//则从header中获取
        }
        return token;
    }
    /**
     * 设置 401 无权限状态
     */
    private void setUnauthorizedResponse(RequestContext requestContext, String msg) {
        log.info("无权限非法请求~");
        requestContext.setSendZuulResponse(false);
        requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        requestContext.getResponse().setCharacterEncoding("UTF-8");
        requestContext.getResponse().setContentType("application/json; charset=utf-8");
        ResultVO resultVO = new ResultVO();
        resultVO.setStatus(401);
        resultVO.setMessage(msg);
        Gson gson = new Gson();
        String result = gson.toJson(resultVO);
        requestContext.setResponseBody(result);
    }
}

###错误拦截器

package com.sgcc.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.enums.ExceptionTypeEnum;
import com.sgcc.zuul.service.ZuulExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author: 杨文培
 * @Desrcription:错误拦截过滤器
 * @Date: Create in 17:43 2018/12/29
 */
@Component
@Slf4j
public class ErrorFilter extends ZuulFilter {
    @Autowired
    private ZuulExceptionService zuulExceptionService;

    @Override
    public String filterType() {
        return FilterConstants.ERROR_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_ERROR_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String url = request.getRequestURI();
        log.info("拦截错误========》》》url={}", url);
        zuulExceptionService.addException(RequestContext.getCurrentContext(), ExceptionTypeEnum.ERROR);
        return null;
    }
}

###后置过滤器

package com.sgcc.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.enums.ExceptionTypeEnum;
import com.sgcc.zuul.service.ZuulExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: 杨文培
 * @Desrcription:后置过滤器
 * @Date: Create in 17:43 2018/12/29
 */
@Component
@Slf4j
public class PostFilter extends ZuulFilter {
    @Autowired
    private ZuulExceptionService zuulExceptionService;

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {

        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();
        String url = request.getRequestURI();
        int status = response.getStatus();
        log.info("网关后置过滤器========》》》url={},status={}", url, status);
        if (200 != status) {
            //网页已经被移到别处
            if (status / 100 != 3) {
                log.info("拦截到一个异常===》url={},status={}", url, status);
                zuulExceptionService.addException(requestContext, ExceptionTypeEnum.EXCEPTION);
            }
        }
        return null;
    }
}

相关标签: 网关