As a gateway service, Zuul is an external transit station for other services, and requests are forwarded through Zuul. This involves that some data cannot be returned intact, such as credentials for communication between services, user encryption information, etc.
For example, the user service provides a login interface. After the user name and password are correct, a token is returned. This token is used as a pass to the user service. Then the token returned after the user logs in successfully, it needs to be encrypted or prevented from tampering. Before arriving at other interfaces of the user service, the token needs to be verified. Illegal tokens do not need to be forwarded to the user service, and the information can be returned directly at the gateway layer.
To modify the information returned by the service, you need to use Zuul's filter. When using it, you only need to inherit ZuulFilter and implement the necessary methods.
Zuul provides the default four filter types, which are identified by filterType method.
The order in which filters are executed is sorted by the filterOrder method, and the smaller the value, the more preferred it is. FilterConstants defines the execution order and routing type of some columns of default filters, and most of the constants that need to be used are here.
As shown in the example, only the login interface needs to be intercepted, so only the login request (/user/login) is needed. You can use the shouldFilter method of the filter to determine whether an interception is required.
Since the data modification is made after the user service is successful, the interceptor type is post type. The implementation of the entire class is as follows:
public class AuthResponseFilter extends AbstractZuulFilter { private static final String RESPONSE_KEY_TOKEN = "token"; @Value("${system.config.authFilter.authUrl}") private String authUrl; @Value("${system.config.authFilter.tokenKey}") private String tokenKey = RESPONSE_KEY_TOKEN; @Autowired private AuthApi authApi; @Override public boolean shouldFilter() { RequestContext context = getCurrentContext(); return StringUtils.equals(context.getRequest().getRequestURI().toString(), authUrl); } @Override public Object run() { try { RequestContext context = getCurrentContext(); InputStream stream = context.getResponseDataStream(); String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); if (StringUtils.isNotBlank(body)) { Gson gson = new Gson(); @SuppressWarnings("unchecked") Map<String, String> result = gson.fromJson(body, Map.class); if (StringUtils.isNotBlank(result.get(tokenKey))) { AuthModel authResult = authApi.encodeToken(result.get(tokenKey)); if (authResult.getStatus() != HttpServletResponse.SC_OK) { throw new IllegalArgumentException(authResult.getErrMsg()); } String accessToken = authResult.getToken(); result.put(tokenKey, accessToken); } body = gson.toJson(result); } context.setResponseBody(body); } catch (IOException e) { rethrowRuntimeException(e); } return null; } @Override public String filterType() { return FilterConstants.POST_TYPE; } @Override public int filterOrder() { return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 2; }} In the configuration file, add the authorization url and return the key token:
system.config.authFilter.authUrl=/user/login
system.config.authFilter.tokenKey=token
context.setResponseBody(body); This code is core, and the returned data is modified through this method.
When the user logs in successfully, token encryption is performed through authorized services based on the returned token. The encryption method here uses JWT. To prevent users from tampering with information, illegal requests can be directly intercepted at the gateway layer.
Regarding the execution process of Zuul filter, there is no need to explain it here. You can tell at a glance the source code. ZuulServletFilter:
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); try { preRouting(); } catch (ZuulException e) { error(e); postRouting(); return; } // Only forward onto to the chain if a zuul response is not being sent if (!RequestContext.getCurrentContext().sendZuulResponse()) { filterChain.doFilter(servletRequest, servletResponse); return; } try { routing(); } catch (ZuulException e) { error(e); postRouting(); return; } try { postRouting(); } catch (ZuulException e) { error(new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_FROM_FILTER_" + e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } }Method Description:
The requested forwarding can be terminated through context.setSendZuulResponse(false), but it can only be set in pre-type filters.
About how to terminate the filter:
Only pre-type filters support termination forwarding, and other filters are executed in sequence. Moreover, pre-type filters can only terminate forwarding after all pre-type filters are executed. The filter cannot be terminated and continued execution. Look at the ZuulServletFilter source code:
// Only forward onto to the chain if a zuul response is not being sent if (!RequestContext.getCurrentContext().sendZuulResponse()) { filterChain.doFilter(servletRequest, servletResponse); return; } The code in this article has been submitted to: https://gitee.com/cmlbeliev/springcloud Welcome to Star
Implementing the class in: com.cml.springcloud.api.filter.AuthResponseFilter under the api-getway project
Local address: http://xz.VeVB.COM:81/201806/yuanma/cmmlbeliev-springcloud_jb51.rar
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.