For various WebUI tools such as Locust that can be used without the need for user authentication I wanted to use it after inserting my own authentication. I found it troublesome to implement the authentication function in each tool as the types of tools increased.
Therefore, place the Spring Cloud Gateway application in front of each tool. Here, all the requests for each tool are accepted and the original authentication is performed. If the authentication is OK, I tried to send the request to the backend tool.
Add "Gateway" to Dependencies in Spring initializr, create a template and download it.
First of all, without authentication function, simply accept the request with Sprin Cloud Gateway, Let's try to distribute the request to the backend tool.
Up to this point, you don't need to implement Java class, you can do it just by setting application.yaml.
This time the Spring Cloud Gateway application listens on port 8080 and http://localhost:8080 Make it accessible with.
The URL of the backend Web UI tool is http://localhost:9001 and http://localhost:9002 will do.
application.yaml
#Spring Cloud Gateway port number settings(You don't have to)
server:
port: 8080
#Spring Cloud Gateway main settings
spring:
cloud:
gateway:
routes:
# -----------------------------------------------------
# http://localhost:8080/tool1/hoge/fuga/...Request
# http://localhost:9001/hoge/fuga/...Flow to
# -----------------------------------------------------
- id: tool1
#Proxy destination
uri: http://localhost:9001
#routing
predicates:
- Path=/tool1/**
#filter(Insert path rewriting and original processing)
filters:
- StripPrefix=1 #Cut off the beginning of the path. In this case"/tool1"Get rid of
# -----------------------------------------------------
# http://localhost:8080/tool2/hoge/fuga/...Request
# http://localhost:9002/hoge/fuga/...Flow to
# -----------------------------------------------------
- id: tool2
#Proxy destination
uri: http://localhost:9002
#routing
predicates:
- Path=/tool2/**
#filter(Insert path rewriting and original processing)
filters:
- StripPrefix=1 #Cut off the beginning of the path. In this case"/tool2"Get rid of
The important one is spring.cloud.gateway.routes, and the outline of each item is as follows.
item | Contents |
---|---|
id | Set any ID |
uri | To send the request(Back end)To set |
predicates | Define what kind of request is made to Spring Cloud Gateway to apply to this routing rule. |
filters | Specify when inserting processing before or after sending a request to the backend. You can also use your own filter class(See below) |
Please refer to Spring Cloud Gateway Official Document to find out what the built-in predicates and filters are. I think.
Instead of the actual WebUI tool, launch a stub server that returns a fixed string with the nc command.
$ (echo "HTTP/1.1 200 ok"; echo; echo "hello") | nc -l 9001
Then make a curl request to Spring Cloud Gateway.
$ curl -v http://localhost:8080/tool1/hoge/fuga
If the Spring Cloud Gateway settings are correct, localhost: 8080 / tool1 / hoge / fuga request It should flow to localhost: 9001 / hoge / fuga.
The contents of the request that came to the stub server are as follows. You can see that the URL path is / hoge / fuga instead of / tool / hoge / fuga.
$ (echo "HTTP/1.1 200 ok"; echo; echo "hello") | nc -l 9001
GET /hoge/fuga HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.64.1
Accept: */*
Forwarded: proto=http;host="localhost:8080";for="0:0:0:0:0:0:0:1:50024"
X-Forwarded-For: 0:0:0:0:0:0:0:1
X-Forwarded-Proto: http
X-Forwarded-Prefix: /tool1
X-Forwarded-Port: 8080
X-Forwarded-Host: localhost:8080
content-length: 0
The result of the curl request is as follows, You can see that Spring Cloud Gateway is returning the response of the stub server on the backend.
$ curl -v http://localhost:8080/tool1/hoge/fuga
> GET /tool1/hoge/fuga HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< transfer-encoding: chunked
<
hello
Next, create your own authentication filter and apply it. This time, extract the value of the "Authorization" key from the HTTP request header If the value is "xxx", authentication is OK and a request is sent to the backend. Otherwise, try creating a filter that returns a 401 Unauthorizaed response as authentication NG.
MyAuthFilter.java The implementation of the filter is as follows, and implement the class that inherits AbstractGatewayFilterFactory.
@Component
public class MyAuthFilter extends AbstractGatewayFilterFactory<MyAuthFilter.Config> {
public MyAuthFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
//Get Authorization Header
ServerHttpRequest request = exchange.getRequest();
String authorizationHeader = Optional.ofNullable(request.getHeaders().get("Authorization"))
.map(h -> {return h.get(0);}).orElse("");
//If the Authorization header is xxx, the request will be sent as it is with successful authentication.
//Otherwise returns a 401 Unauthorized response
if(authorizationHeader.equals("xxx")) {
return chain.filter(exchange.mutate().request(request).build());
} else {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
};
}
public static class Config {
}
}
application.yaml Just creating your own filter class as described above will not be reflected yet. If you want to apply your own filter, go to the filters item in application.yaml. I will write the class name of this unique filter.
The whole picture of application.yaml is as follows, and only the two lines that say "[Add]" are added.
#Spring Cloud Gateway main settings
spring:
cloud:
gateway:
routes:
# -----------------------------------------------------
# http://localhost:8080/tool1/hoge/fuga/...Request
# http://localhost:9001/hoge/fuga/...Flow to
# -----------------------------------------------------
- id: tool1
#Proxy destination
uri: http://localhost:9001
#routing
predicates:
- Path=/tool1/**
#filter(Insert path rewriting and original processing)
filters:
- MyAuthFilter # [add to]Insert your own authentication filter
- StripPrefix=1 #Cut off the beginning of the path. In this case"/tool1"Get rid of
# -----------------------------------------------------
# http://localhost:8080/tool2/hoge/fuga/...Request
# http://localhost:9002/hoge/fuga/...Flow to
# -----------------------------------------------------
- id: tool2
#Proxy destination
uri: http://localhost:9002
#routing
predicates:
- Path=/tool2/**
#filter(Insert path rewriting and original processing)
filters:
- MyAuthFilter # [add to]Insert your own authentication filter
- StripPrefix=1 #Cut off the beginning of the path. In this case"/tool2"Get rid of
#Spring Cloud Gateway port number settings(You don't have to)
server:
port: 8080
Launch the stub server on port 9001 as before, Request without Authorization header as below Make a curl request with an Authorization header.
$ curl -v http://localhost:8080/tool1/hoge/fuga
$ curl -H 'Authorization: xxx' -v http://localhost:8080/tool1/hoge/fuga
If you request without the Authrozation header, as implemented in MyAuthFilter, A 401 Unauthorized response is returned.
$ curl -v http://localhost:8080/tool1/hoge/fuga
> GET /tool1/hoge/fuga HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< content-length: 0
<
You can also see that no request has arrived on the stub server side.
$ (echo "HTTP/1.1 200 ok"; echo; echo "hello") | nc -l 9001
* No change
Next, when you request by setting the value of xxx in the Authrozation header, The hello string returned by the stub server is returned.
$ curl -H 'Authorization: xxx' -v http://localhost:8080/tool1/hoge/fuga
> GET /tool1/hoge/fuga HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Authorization: xxx
>
< HTTP/1.1 200 OK
< transfer-encoding: chunked
<
hello
You can see that the request is also coming to the stub server side.
$ (echo "HTTP/1.1 200 ok"; echo; echo "hello") | nc -l 9001
GET /hoge/fuga HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.64.1
Accept: */*
Authorization: xxx
Forwarded: proto=http;host="localhost:8080";for="0:0:0:0:0:0:0:1:50517"
X-Forwarded-For: 0:0:0:0:0:0:0:1
X-Forwarded-Proto: http
X-Forwarded-Prefix: /tool1
X-Forwarded-Port: 8080
X-Forwarded-Host: localhost:8080
content-length: 0
For the time being, it seems possible to control whether authentication is OK or NG and whether or not to send a request to the back end.
site | Overview |
---|---|
Play with Spring Cloud Gateway | First read page |
Spring Cloud Gateway | Official Spring documentation. There is a lot of information about the built-in Predicates and Filters. There is also a little explanation about the self-made Filter. |
Spring Cloud Gateway - Creating Custom Route Filters (AbstractGatewayFilterFactory) | Implementation of self-made Filter and application.For the setting method in yaml, I mainly referred to this page. |
Recommended Posts