基於【 建造者模式】一 || 網關zuul過濾器封裝

1、springcloud的zuul網關攔截

一、黑名單攔截spring

二、參數驗籤數據庫

三、Api接口權限驗證設計模式

2、網關攔截實現方式

一、繼承ZuulFilter方法,實現業務邏輯api

@Component
@Slf4j
public class GatewayFilter extends ZuulFilter {

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

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

    @Override
    public boolean shouldFilter() {
        // 改成true,纔會走run方法
        return true;
    }


    /**
     * 請求以前攔截處理業務邏輯
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {

        RequestContext ctx = RequestContext.getCurrentContext();
        // 1.獲取請求對象
        HttpServletRequest request = ctx.getRequest();
        // 2.獲取響應對象
        HttpServletResponse response = ctx.getResponse();

        // 3.獲取客戶端真實ip地址
        String ipAddr = IpUtil.getIpAddr(request);
        if (StringUtils.isEmpty(ipAddr)) {
            resultError(ctx, "未可以獲取到ip地址");
        }
        // 4.動態獲取黑名單列表,判斷是黑名單,設置網關響應爲false
        if("127.0.0.1".equals(ipAddress)){
            resultError(ctx, "ip:" + ipAddress + ",Insufficient access rights");
        }
        // 5.傳遞參數簽名攔截
        Map<String, String> verifyMap = SignUtil.toVerifyMap(request.getParameterMap(), false);
        if(!SignUtil.verify(verifyMap)){
            resultError(ctx, "ip:" + ipAddress + ",Sign fail");
        }
        // 6.api權限驗證
        String servletPath = request.getServletPath();
        String accessToken = request.getParameter("accessToken");if (StringUtils.isEmpty(accessToken)) {
            resultError(ctx, "AccessToken cannot be empty");
        }
        // 調用接口驗證accessToken是否失效
        BaseResponse<JSONObject> appInfo = verificaCodeServiceFeign.getAppInfo(accessToken);if (!isSuccess(appInfo)) {
            resultError(ctx, appInfo.getMsg());
        }

        return null;

    }


    /**
     * 錯誤返回
     * @param ctx
     * @param code
     * @param errorMsg
     */
    private void resultError(RequestContext ctx, String errorMsg) {
        ctx.setResponseStatusCode(401);
        // 網關響應爲false 不會轉發服務
        ctx.setSendZuulResponse(false);
        ctx.setResponseBody(errorMsg);

    }

3、使用建造者模式對上面代碼進行封裝

一、基於建造者設計模式封裝: 網關權限控制app

public interface GatewayBuild {

    /**
     * 黑名單攔截
     */
    Boolean blackBlock(RequestContext ctx, String ipAddress, HttpServletResponse response);

    /**
     * 參數驗籤
     */
    Boolean paramsValidate(RequestContext ctx, String ipAddress, HttpServletRequest request);

    /**
     * api權限控制
     *
     * @return
     */
    Boolean apiAuthorize(RequestContext ctx, HttpServletRequest request);
}

二、基於建造者設計模式封裝: 參數驗證build,業務邏輯的實現ide

@Slf4j
@Component
public class VerificationBuild implements GatewayBuild {
    @Override
    public Boolean blackBlock(RequestContext ctx, String ipAddress, HttpServletResponse response) {
        // 4.從數據庫動態讀取,判斷是黑名單,設置網關響應爲false
        if("127.0.0.1".equals(ipAddress)){
            resultError(ctx, "ip:" + ipAddress + ",Insufficient access rights");
            return false;
        }
        log.info(">>>>>>ip:{},驗證經過>>>>>>>", ipAddress);
        return true;
    }

    @Override
    public Boolean paramsValidate(RequestContext ctx, String ipAddress, HttpServletRequest request) {
        // 5.外網傳遞參數簽名攔截
        Map<String, String> verifyMap = SignUtil.toVerifyMap(request.getParameterMap(), false);
        if(!SignUtil.verify(verifyMap)){
            resultError(ctx, "ip:" + ipAddress + ",Sign fail");
            return false;
        }
        return true;
    }

    @Override
    public Boolean apiAuthorize(RequestContext ctx, HttpServletRequest request) {
        String servletPath = request.getServletPath();
        // 內部服務調用不須要accessToken驗證,若是public開頭,表示受權方訪問接口
        if (!servletPath.substring(0, 7).equals("/public")) {
            return true;
        }
        String accessToken = request.getParameter("accessToken");
        log.info(">>>>>accessToken驗證:" + accessToken);
        if (StringUtils.isEmpty(accessToken)) {
            resultError(ctx, "AccessToken cannot be empty");
            return false;
        }
        // 調用接口驗證accessToken是否失效
        BaseResponse<JSONObject> appInfo = verificaCodeServiceFeign.getAppInfo(accessToken);
        log.info(">>>>>>data:" + appInfo.toString());
        if (!isSuccess(appInfo)) {
            resultError(ctx, appInfo.getMsg());
            return false;
        }
        return true;
    }

    /**
     * 網關攔截
     * @param ctx
     * @param code
     * @param errorMsg
     */
    private void resultError(RequestContext ctx, String errorMsg) {
        ctx.setResponseStatusCode(401);
        // 網關響應爲false 不會轉發服務
        ctx.setSendZuulResponse(false);
        ctx.setResponseBody(errorMsg);

    }
}

三、基於建造者設計模式封裝: 鏈接Buildui

@Component
public class GatewayDirector {

    @Resource(name = "VerificationBuild")
    private GatewayBuild gatewayBuild;
    /**
     * 鏈接建造者
     * @param ctx
     * @param ipAddress
     * @param response
     * @param request
     */
    public void direcot(RequestContext ctx, String ipAddress, HttpServletResponse response, HttpServletRequest request){

        // 1.黑名單
        Boolean boolBlackBlock = gatewayBuild.blackBlock(ctx, ipAddress, response);
        if(!boolBlackBlock){
            return;
        }
        // 2.參數驗證
        Boolean boolParamsValidate = gatewayBuild.paramsValidate(ctx, ipAddress, request);
        if(!boolParamsValidate){
            return;
        }
        // 3.api權限控制
        Boolean boolApiAuthorize = gatewayBuild.apiAuthorize(ctx, request);
        if(!boolApiAuthorize){
            return;
        }

    }
}

四、網關過濾器中調用spa

@Override
    public Object run() throws ZuulException {

        // 設計模式一: 基於建造者模式封裝
        RequestContext ctx = RequestContext.getCurrentContext();
        // 1.獲取請求對象
        HttpServletRequest request = ctx.getRequest();
        // 2.獲取響應對象
        HttpServletResponse response = ctx.getResponse();

        // 3.獲取客戶端真實ip地址
        String ipAddr = IpUtil.getIpAddr(request);
        if (StringUtils.isEmpty(ipAddr)) {
            resultError(ctx, "未可以獲取到ip地址");
        }

        // 4.基於建造者模式封裝: 進行請求限制
        gatewayDirector.direcot(ctx,ipAddr,response,request);

        return null;



    }
相關文章
相關標籤/搜索