春ブーツZuul認証

簡易認証を行います

トークン認証、検証トークン

通常、このような認証zuulゲートウェイレベルなどの操作を確認し、認証に加えて、それはまた、暗号化を制限することができます。

継承ZuulFilter、

ZuulFilter出典: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);
        }

    }
}

4つの方法のキー:

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

実行():ビジネス・ロジックの具体的な実装

shouldFilter():フィルタは、フィルタは、実質的に濾過するフィルタのニーズを実行する真であるかどうか

filterOrder():実行優先度フィルタ、高い優先度である
のfilterType():フィルタの種類、ポスト、予め、ルート、エラーがあります

PRE:リクエストルーティングにおけるフィルタのこのタイプは、前ソースのWebサービスに行きました。ソース・サービス・アドレスを選択し、認証を実装するための
ルーティング:ウェブサービスのソースへのルーティング要求で使用されるフィルタの種類を、ソースには、Webサービスのビジネス・ロジック・サービスです。ここで使用されるように、HttpClientを要求されたWebサービス。
POST:フィルタの種類は、リターン応答をルーティングを行っています。修正する結果と同様に、統計データの収集は、応答クライアントが送信されますを達成するためのレスポンス。
ERROR:フィルタのいずれかのエラーERRORタイプ上記の3つのプロセスが処理のために引き渡されています。
主な関心事の事前、事後およびエラー。プレフィルタ、ポストフィルタおよびフィルタの異常を表しています。

この設定ツールは、すべてのクラスで見つけることができFilterConstants以上4

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(偽);ここで注意すべきは、このセットは、バックエンドサーバーを要求するルート虚偽をしないということです。しかし、他のフィルタの実施を継続する必要があり、検証が渡されない場合は、通常通りのフィルタを行い背後には、フィルタはので、ここで、この後部フィルタではありませんが、また場合。他のshouldFilterフィルタに()メソッドは、より良い少しに以下を添加することによって決定されます。

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

 

最初のトークン文字列のRedisに、ランダム、テストのために

戻り値が与えられています

トークン検証した後、

トークンを渡しません再びそれを試してみてください

 

あなたが見ていないトークン401検証

 

 

 

公開された288元の記事 ウォン称賛88 ビュー430 000 +

おすすめ

転載: blog.csdn.net/ypp91zr/article/details/90277413