微服务-springcloud-zuul

#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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值