SpringCloudAlibaba 企业级应用实战:SpringCloudGateway 基于服务发现实现认证服务

SpringCloudGateway 基于服务发现实现认证服务

案例说明

本案例使用SpringCloud Alibaba Nacos做为服务发现,使用SpringCloudGateway做为微服务统一网关服务。java

工程实现步骤

引入相关依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>

网关配置文件

server:
  port: 7004
spring:
  application:
    name: sca-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
      - id: sca-account-consumer
        uri: lb://sca-account-consumer
        predicates:
        - Path=/sca-account-consumer/**
  main:
    allow-bean-definition-overriding: true

全局认证过滤器

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;


@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String token = exchange.getRequest().getQueryParams().getFirst("token");

        if (token == null || "".equals(token)) {
            ServerHttpResponse response = exchange.getResponse();

            Map<String, Object> responseMap = new HashMap<String, Object>();
            responseMap.put("success", Boolean.FALSE);
            responseMap.put("message", "非法请求");

            ObjectMapper objectMapper = new ObjectMapper();
            try {
                byte[] bytes = objectMapper.writeValueAsBytes(responseMap);
                DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);

                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

                return response.writeWith(Mono.just(dataBuffer));

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        }

        return chain.filter(exchange);
    }

    public int getOrder() {
        return 0;
    }
}

启动类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ScaGatewayApplication implements CommandLineRunner {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

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

    public void run(String... args) throws Exception {
        logger.info("------------ 网关应用启动成功 -------------");
    }
}

测试

  1. 启动Nocos Server
  2. 启动sca-account-servicesca-account-consumer工程。这两个工程分别是帐户服务的提供者和消费者,经过sca-gateway网关访问这两个服务。
  3. 启动sca-gateway服务。

非法请求测试:
浏览器输入:http://localhost:7004/sca-account-consumer/register?name=tyrone,响应结果以下图:
在这里插入图片描述
由于该请求没有携带token用户身份标识,因此返回非法请求。react

合法请求测试:
浏览器输入带 token 的请求:http://localhost:7004/sca-account-consumer/register?name=tyrone&token=Tyrone,响应结果以下图:
在这里插入图片描述git

引用