前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >独立使用zuul网关分发不同服务的请求、权限控制,非SpringCloud

独立使用zuul网关分发不同服务的请求、权限控制,非SpringCloud

作者头像
天涯泪小武
发布2019-01-17 11:43:41
1.4K0
发布2019-01-17 11:43:41
举报
文章被收录于专栏:SpringCloud专栏SpringCloud专栏

网关api Gateway的重要性不言而喻,网关负责统一接收所有请求,然后根据不同的规则进行转发到不同的服务。使用网关能够统一的管理请求日志、进行权限控制、过滤等,这样就能避免在每个单体应用中做重复的工作。

这一篇主要是讲zuul的独立使用,就是只作为一个独立的项目进行请求转发,而不关联SpringCloud的那一堆Eureka、Ribbon等,因为很多时候我们的项目并不都是基于springcloud的微服务,或者不想搞那么麻烦用注册中心什么的,就只想做个简单的请求转发代理和权限控制。

zuul是可以进行开发的,里面可以自定义一些自己的规则,譬如涉及查表之类的,能够完成颗粒很细的需求。

这里我们打算完成如下的功能,当访问ip/user时就进入到User的独立项目中,访问ip/club时就进入到club的独立项目中。入口是zuul,在zuul里做权限控制,譬如查表过滤黑名单、限制同一个userId单位时间内的访问次数等。

请求转发

使用zuul很简单,新建一个Springboot项目,创建时勾选zuul即可。pom.xml如下

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.tianyalei</groupId>
	<artifactId>testzuul</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>testzuul</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Dalston.SR3</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

然后在Application类加上@EnableZuulProxy注解即可,该项目就具备了zuul的功能了

代码语言:javascript
复制
@EnableZuulProxy
@SpringBootApplication
public class TestzuulApplication {

	public static void main(String[] args) {
		SpringApplication.run(TestzuulApplication.class, args);
	}
}

然后关键的地方在application.yml配置里,规则在这里配置

代码语言:javascript
复制
server:
  port: 9000
zuul:
  routes:
    api-1:
      path: /user/**
      url: http://localhost:8081/
    api-2:
      path: /club/**
      url: http://localhost:8082/

主要就是配置zuul.routes相关,api-1名字随便起,主要是配置里面的path和url这个是固定的

通过源码可以看到支持serviceId,url两种,path是固定的,代表访问zuul时的路径,url代表访问该路径时会被转发到哪个url上,serviceId是给springcloud用的,代表在Eureka上注册的服务id,也是确定是转发到哪一个服务的。

这里我们配置的是url,当访问localhost:9000/user/abc时,就相当于访问localhost:8081/abc.

到这里就已经完成了请求转发了,如果你本地跑了两个项目,端口分别是8081,8082,就已经可以通过请求zuul配置的url规则访问到了。

代码语言:javascript
复制
@RequestMapping("club")
    public String index() {
        return "hello,我来自Club客户端";
    }

权限控制

在zuul里新建一个AccessFilter类,如下的写法。

代码语言:javascript
复制
package com.tianyalei.testzuul;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class AccessFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

    @Override
    public String filterType() {
        //前置过滤器
        return "pre";
    }

    @Override
    public int filterOrder() {
        //优先级,数字越大,优先级越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        //是否执行该过滤器,true代表需要过滤
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

        //获取传来的参数accessToken
        Object accessToken = request.getParameter("accessToken");
        if(accessToken == null) {
            log.warn("access token is empty");
            //过滤该请求,不往下级服务去转发请求,到此结束
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"result\":\"accessToken is empty!\"}");
            return null;
        }
        //如果有token,则进行路由转发
        log.info("access token ok");
        //这里return的值没有意义,zuul框架没有使用该返回值
        return null;
    }

}

别的先不管,看看run方法,在这里可以获取到用户传来的所有参数,然后可以配置自己的规则来决定是否往最终的服务转发请求,false为不给最终的服务发送这次请求,默认为true。在这里,我们设置如果accessToken为空,就停止转发,直接给客户端返回结果。需要注意一点,Filter是可以配置多个的,按照order从小到大依次执行,即使设置了setSendZuulResponse(false),也是会继续执行下一个Filter的。

注意,路由转发的停止和继续是由ctx.setSendZuulResponse来控制的,与下面的return null无关,这个方法的return值没有意义,并没有使用。

效果如图

下一篇来详细看看Filter的配置。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年09月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 请求转发
  • 权限控制
相关产品与服务
API 网关
腾讯云 API 网关(API Gateway)是腾讯云推出的一种 API 托管服务,能提供 API 的完整生命周期管理,包括创建、维护、发布、运行、下线等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档