Spring Cloud - Gateway

Use Zuul to build a gateway

Zuul's Filter configuration

  • Inherit the ZuulFilter class and override the method
import javax.servlet.http.HttpServletRequest;  
  
import com.netflix.zuul.ZuulFilter;  
import com.netflix.zuul.context.RequestContext;  
  
public class AccessUserNameFilter extends ZuulFilter {  
    @Override  
    public Object run() {  
        RequestContext ctx = RequestContext.getCurrentContext();  
        HttpServletRequest request = ctx.getRequest();  
  
        System.out.println(String.format("%s AccessUserNameFilter request to %s", request.getMethod(), request.getRequestURL().toString()));  
  
        String username = request.getParameter("username");// 获取请求的参数  
        if(null != username && username.equals("chhliu")) {// 如果请求的参数不为空,且值为chhliu时,则通过  
            ctx.setSendZuulResponse(true);// 对该请求进行路由  
            ctx.setResponseStatusCode(200);  
            ctx.set("isSuccess", true);// 设值,让下一个Filter看到上一个Filter的状态  
            return null;  
        }else{  
            ctx.setSendZuulResponse(false);// 过滤该请求,不对其进行路由  
            ctx.setResponseStatusCode(401);// 返回错误码  
            ctx.setResponseBody("{\"result\":\"username is not correct!\"}");// 返回错误内容  
            ctx.set("isSuccess", false);  
            return null;  
        }  
    }  
  
    @Override  
    public boolean shouldFilter() {  
        return true;// 是否执行该过滤器,此处为true,说明需要过滤  
    }  
  
    @Override  
    public int filterOrder() {  
        return 0;// 优先级为0,数字越大,优先级越低  
    }  
  
    @Override  
    public String filterType() {  
        return "pre";// 前置过滤器  
    }  
}

By inheriting ZuulFilter and then overriding the above four methods, a simple filter can be implemented. The relevant points of attention are explained below:

  • filterType: Returns a string representing the type of the filter. Four types of filters with different life cycles are defined in zuul, as follows:
  1. pre: can be called before the request is routed
  2. route: called when routing requests
  3. post: called after the route and error filters
  4. error: called when an error occurs while processing the request
  • Zuul's main request lifecycle includes phases such as "pre", "route" and "post". For every request, all filters with these types are run.
  • filterOrder: define the execution order of the filter by int value
  • shouldFilter: returns a boolean type to determine whether the filter is to be executed, so the switch of the filter can be realized through this function. In the above example, we directly return true, so the filter always takes effect
  • run: The specific logic of the filter. It should be noted that here we use ctx.setSendZuulResponse(false) to make zuul filter the request without routing it, and then set the error code returned by it through ctx.setResponseStatusCode(401)    

Following the above example, multiple filters can be created, which are called in different life cycles according to different filter types. For details, please refer to: Spring cloud-zuul's Filter Detailed Explanation

Token renewal processing

The processing method is the same as the custom filter class above, and the filterType is set to "post". The principle is that the post is called after the route and error filters, indicating that it has been legally passed. At this time, it is decided whether to renew the lease based on whether the Token is about to expire. The judgment rule below is to renew the lease when it is less than 60*20=1200

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.finshell.hyacinthcloud.base.enums.ErrorCodeEnum;
import com.finshell.hyacinthcloud.base.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.stereotype.Component;

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

/**
 * The class Renew filter.
 *
 * @author [email protected]
 */
@Component
@Slf4j
public class RenewFilter extends ZuulFilter {

	@Resource
	private JwtTokenStore jwtTokenStore;
	private static final int EXPIRES_IN = 60 * 20;

	/**
	 * Filter type string.
	 *
	 * @return the string
	 */
	@Override
	public String filterType() {
		return "post";
	}

	/**
	 * Filter order int.
	 *
	 * @return the int
	 */
	@Override
	public int filterOrder() {
		return 10;
	}

	/**
	 * Should filter boolean.
	 *
	 * @return the boolean
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
	 * Run object.
	 *
	 * @return the object
	 */
	@Override
	public Object run() {
		log.info("RenewFilter - token续租...");
		RequestContext requestContext = RequestContext.getCurrentContext();
		try {
			doSomething(requestContext);
		} catch (Exception e) {
			log.error("RenewFilter - token续租. [FAIL] EXCEPTION={}", e.getMessage(), e);
			throw new BusinessException(ErrorCodeEnum.UAC10011041);
		}
		return null;
	}

	private void doSomething(RequestContext requestContext) {
		HttpServletRequest request = requestContext.getRequest();
		String token = StringUtils.substringAfter(request.getHeader(HttpHeaders.AUTHORIZATION), "bearer ");
		if (StringUtils.isEmpty(token)) {
			return;
		}
		OAuth2AccessToken oAuth2AccessToken = jwtTokenStore.readAccessToken(token);
		int expiresIn = oAuth2AccessToken.getExpiresIn();

		if (expiresIn < EXPIRES_IN) {
			HttpServletResponse servletResponse = requestContext.getResponse();
			servletResponse.addHeader("Renew-Header", "true");
		}
	}

}

Available reference materials:

Guess you like

Origin blog.csdn.net/qq_28202661/article/details/102895339