la autenticación de la primavera de arranque Zuul

Hacer una autenticación simple

token de autenticación, verificación de contadores

Por lo general, verificar las operaciones tales como la autenticación zuul gateway nivel, además de la autenticación, puede también ser limitante, el cifrado.

La herencia ZuulFilter,

ZuulFilter Fuente: implementado en IZuulFilter

 * Copyright 2013 Netflix, Inc.
package com.netflix.zuul;

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.zuul.monitoring.MonitoringHelper;
import com.netflix.zuul.monitoring.Tracer;
import com.netflix.zuul.monitoring.TracerFactory;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.*;

/**
 * Base abstract class for ZuulFilters. The base class defines abstract methods to define:
 * filterType() - to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
 * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
 * We also support a "static" type for static responses see  StaticResponseFilter.
 * Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
 * <p/>
 * filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not
 * important for a filter. filterOrders do not need to be sequential.
 * <p/>
 * ZuulFilters may be disabled using Archius Properties.
 * <p/>
 * By default ZuulFilters are static; they don't carry state. This may be overridden by overriding the isStaticFilter() property to false
 *
 * @author Mikey Cohen
 *         Date: 10/26/11
 *         Time: 4:29 PM
 */
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {

    private final AtomicReference<DynamicBooleanProperty> filterDisabledRef = new AtomicReference<>();

    /**
     * to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
     * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
     * We also support a "static" type for static responses see  StaticResponseFilter.
     * Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
     *
     * @return A String representing that type
     */
    abstract public String filterType();

    /**
     * filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not
     * important for a filter. filterOrders do not need to be sequential.
     *
     * @return the int order of a filter
     */
    abstract public int filterOrder();

    /**
     * By default ZuulFilters are static; they don't carry state. This may be overridden by overriding the isStaticFilter() property to false
     *
     * @return true by default
     */
    public boolean isStaticFilter() {
        return true;
    }

    /**
     * The name of the Archaius property to disable this filter. by default it is zuul.[classname].[filtertype].disable
     *
     * @return
     */
    public String disablePropertyName() {
        return "zuul." + this.getClass().getSimpleName() + "." + filterType() + ".disable";
    }

    /**
     * If true, the filter has been disabled by archaius and will not be run
     *
     * @return
     */
    public boolean isFilterDisabled() {
        filterDisabledRef.compareAndSet(null, DynamicPropertyFactory.getInstance().getBooleanProperty(disablePropertyName(), false));
        return filterDisabledRef.get().get();
    }

    /**
     * runFilter checks !isFilterDisabled() and shouldFilter(). The run() method is invoked if both are true.
     *
     * @return the return from ZuulFilterResult
     */
    public ZuulFilterResult runFilter() {
        ZuulFilterResult zr = new ZuulFilterResult();
        if (!isFilterDisabled()) {
            if (shouldFilter()) {
                Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());
                try {
                    Object res = run();
                    zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
                } catch (Throwable e) {
                    t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
                    zr = new ZuulFilterResult(ExecutionStatus.FAILED);
                    zr.setException(e);
                } finally {
                    t.stopAndLog();
                }
            } else {
                zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
            }
        }
        return zr;
    }

    public int compareTo(ZuulFilter filter) {
        return Integer.compare(this.filterOrder(), filter.filterOrder());
    }

    public static class TestUnit {

        static Field field = null;
        static {
            try {
                field = ZuulFilter.class.getDeclaredField("filterDisabledRef");
                field.setAccessible(true);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        @Mock
        private ZuulFilter f1;
        @Mock
        private ZuulFilter f2;

        @Before
        public void before() {
            MockitoAnnotations.initMocks(this);
            MonitoringHelper.initMocks();
        }

        @Test
        public void testSort() {

            when(f1.filterOrder()).thenReturn(1);
            when(f2.filterOrder()).thenReturn(10);
            when(f1.compareTo(any(ZuulFilter.class))).thenCallRealMethod();
            when(f2.compareTo(any(ZuulFilter.class))).thenCallRealMethod();

            ArrayList<ZuulFilter> list = new ArrayList<ZuulFilter>();
            list.add(f2);
            list.add(f1);

            Collections.sort(list);

            assertSame(f1, list.get(0));
        }

        @Test
        public void testShouldFilter() {
            class TestZuulFilter extends ZuulFilter {

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

                @Override
                public int filterOrder() {
                    return 0;
                }

                public boolean shouldFilter() {
                    return false;
                }

                public Object run() {
                    return null;
                }
            }

            TestZuulFilter tf1 = spy(new TestZuulFilter());
            TestZuulFilter tf2 = spy(new TestZuulFilter());

            when(tf1.shouldFilter()).thenReturn(true);
            when(tf2.shouldFilter()).thenReturn(false);

            try {
                tf1.runFilter();
                tf2.runFilter();
                verify(tf1, times(1)).run();
                verify(tf2, times(0)).run();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }

        }

        @Test
        public void testIsFilterDisabled() {
            class TestZuulFilter extends ZuulFilter {

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

                @Override
                public int filterOrder() {
                    return 0;
                }

                public boolean isFilterDisabled() {
                    return false;
                }

                public boolean shouldFilter() {
                    return true;
                }

                public Object run() {
                    return null;
                }
            }

            TestZuulFilter tf1 = spy(new TestZuulFilter());
            TestZuulFilter tf2 = spy(new TestZuulFilter());

            when(tf1.isFilterDisabled()).thenReturn(false);
            when(tf2.isFilterDisabled()).thenReturn(true);

            try {
                tf1.runFilter();
                tf2.runFilter();
                verify(tf1, times(1)).run();
                verify(tf2, times(0)).run();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }

        }

        @Test
        public void testDisabledPropNameOnInit() throws Exception {
            class TestZuulFilter extends ZuulFilter {

                final String filterType;

                public TestZuulFilter(String filterType) {
                    this.filterType = filterType;
                }

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

                @Override
                public Object run() {
                    return null;
                }

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

                @Override
                public int filterOrder() {
                    return 0;
                }
            }

            TestZuulFilter filter = new TestZuulFilter("pre");
            assertFalse(filter.isFilterDisabled());

            @SuppressWarnings("unchecked")
            AtomicReference<DynamicBooleanProperty> filterDisabledRef = (AtomicReference<DynamicBooleanProperty>) field.get(filter);
            String filterName = filterDisabledRef.get().getName();
            assertEquals("zuul.TestZuulFilter.pre.disable", filterName);
        }

    }
}

La clave de cuatro métodos:

@Override
	public Object run() throws ZuulException {
		return null;
	}

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

	@Override
	public int filterOrder() {
		return 0;
	}

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

ejecutar (): la implementación específica de la lógica de negocio

shouldFilter (): si el filtro, el filtro es, en efecto, es cierto para ejecutar las necesidades de filtro a filtrar

filterOrder (): filtro de prioridad de ejecución, son una prioridad más alta
FilterType (): tipo de filtro, hay post, pre, ruta, error

PRE: Este tipo de filtros en la solicitud de enrutamiento realiza antes del servicio web de origen. Para la implementación de autenticación, seleccione la dirección de servicio de origen
de enrutamiento: el tipo de filtros utilizados en la solicitud de enrutamiento a una fuente de servicios web, la fuente es un servicio web de servicios de lógica de negocios. Como se usa en el presente documento, HttpClient web-servicio solicitado.
POST: El tipo de los filtros se realiza el enrutamiento de respuesta de retorno. Respuesta a lograr los resultados que se desea modificar, así como la recopilación de datos estadísticos se transmitirán los clientes de respuesta.
ERROR: tres procesos por encima de cualquier tipos de error error de filtros son entregados para su procesamiento.
La principal preocupación pre, post y error. Representar las anormalidades pre-filtro, el post-filtro y el filtro.

Más de cuatro de cada FilterConstants esta herramienta de configuración se encuentra en todas las clases

TokenAuthFilter:

package com.chwl.cn.token;

import java.util.Objects;
import java.util.UUID;

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

import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import com.chwl.cn.config.redis.RedisUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

@Component
public class TokenAuthFilter extends ZuulFilter  {
	
	@Autowired
	private RedisUtils redisUtils;
	
	//排除过滤的 uri 地址
    private static final String LOGIN_URI = "/user/login";
    private static final String REGISTER_URI = "/user/register";
    
    private static final String AUTH_TOKEN = "token";

	@Override
	public Object run() throws ZuulException {
		RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();
        String token = request.getHeader(AUTH_TOKEN);
        	Object object = redisUtils.get(token);
        	//token存在,删除原来的token,重新生成token返回给客户端
        	if(!Objects.isNull(object)){
        		redisUtils.del(token);
        		String uuidToken = UUID.randomUUID().toString();
        		redisUtils.set(uuidToken,uuidToken);
        		response.setHeader("Access-Control-Expose-Headers",
        				"Cache-Control,Content-Type,Expires,Pragma,Content-Language,Last-Modified,token");
        		response.setHeader("token", uuidToken); // 设置响应头
        		response.setStatus(HttpStatus.SC_OK);
        		requestContext.setResponseBody("token验证成功!");
        	}else {
        		//不存在,直接返回验证失败,让其重新登录
        		requestContext.setSendZuulResponse(false);//不会被zuul路由转发,也就是不会请求到后端具体的服务。但是如果当前filter后面还有其他filter的话,其他filter依然会执行
//        		requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);//和response.setStatus(HttpStatus.SC_UNAUTHORIZED);一样的效果
        		response.setStatus(HttpStatus.SC_UNAUTHORIZED);//401
        		requestContext.setResponseBody("token验证失败!");
        	}
        	return null;
	}

	@Override
	public boolean shouldFilter() {
		RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();
        String requestURI = request.getRequestURI();
        //登录和注册放行
        if(LOGIN_URI.equals(requestURI)||REGISTER_URI.equals(requestURI)){
        	String uuidToken = UUID.randomUUID().toString();
    		redisUtils.set(uuidToken,uuidToken);
    		response.setHeader("Access-Control-Expose-Headers",
    				"Cache-Control,Content-Type,Expires,Pragma,Content-Language,Last-Modified,token");
    		response.setHeader("token", uuidToken); // 设置响应头
        	return false;
        }
		return true;
	}

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

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

}

requestContext.setSendZuulResponse (falso); a tener en cuenta es que este conjunto no lo hace falsa ruta para solicitar el servidor back-end. Pero si la hay, entonces filtrar detrás de los filtros lleva a cabo como de costumbre en este filtro trasera, por lo que aquí si la verificación no se pasa, sino que también hay necesidad de continuar la ejecución del otro filtro. En otro filtro shouldFilter método () se determina mediante la adición de lo siguiente para un poco mejor:

@Override
public boolean shouldFilter() {
    RequestContext ctx = RequestContext.getCurrentContext();
 
    if(!ctx.sendZuulResponse()){
        return false;
    }
    return true;
}

 

En primer lugar en una cadena símbolo Redis, al azar, para la prueba

se le da el valor de retorno

Después de una verificación de contadores

Inténtelo de nuevo no pasar el token

 

401 de verificación de contadores que no has visto

 

 

 

Publicados 288 artículos originales · ganado elogios 88 · vistas 430 000 +

Supongo que te gusta

Origin blog.csdn.net/ypp91zr/article/details/90277413
Recomendado
Clasificación