首页 > 解决方案 > 如何在spring cloud api网关终止请求流并重定向到不同的URL路由路径

问题描述

我已经实现了以下微服务应用程序。

请求流。

ui Client(http://localhost:8080) ------> spring cloud gateway(http://localhost:8081) ------> 用户微服务(http://localhost:8602)(api端点=/api/v1/users/bulkUpload)

我正在通过 spring 云网关服务向用户微服务发送 Ajax 请求。Ajax 请求包含刷新令牌作为 cookie 值。

     $.ajax({
                type: "POST",
                enctype: 'multipart/form-data',
                url: "http://localhost:8081/api/v1/users/bulkUpload",
                xhrFields: {
                    withCredentials: true
                },
                data: newData,
                processData: false,
                contentType: false,
                crossDomain: false,
                cache: false,
                timeout: 600000,
                success: function (data) {
......
}

但是如果刷新令牌在 Ajax 请求中不可用,我想在 API 网关级别终止请求,并且我想将用户重定向到 Ui 客户端注销页面(http://localhost:8080/Logout)。为此,我实现了一个弹簧云网关过滤器,如下所示。

@Component
public class AccessTokenCheckingGlobalFilterPre extends AbstractGatewayFilterFactory<AccessTokenCheckingGlobalFilterPre.Config> {

    @Value("${security.oauth2.client.client-id}")
    private String client_id;

    @Value("${security.oauth2.client.client-secret}")
    private String client_secret;

    
    
    public AccessTokenCheckingGlobalFilterPre() {
        super(AccessTokenCheckingGlobalFilterPre.Config.class);
    }

    @Override
    public GatewayFilter apply(AccessTokenCheckingGlobalFilterPre.Config config) {
        return (exchange, chain) -> {
             Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
             ServerHttpRequest request = exchange.getRequest();
             ServerHttpResponse response = exchange.getResponse();
             
             if(route!=null && request.getPath().toString().contains("oauth/token")) {
                 
                 return chain.filter(exchange.mutate().request(request).response(response).build());

             }else {
                
                 MultiValueMap<String, HttpCookie> cookies = request.getCookies();
                 List<HttpCookie> accessTokenList =  cookies.get("access_token");
                 List<HttpCookie> refreshTokenList =  cookies.get("refresh_token");
                 HttpHeaders heraders = request.getHeaders();
                 String access_token="";
                 String refresh_token = "";
                 if(accessTokenList != null) {
                   access_token = accessTokenList.get(0).getValue();
                 }
                 
                 if(refreshTokenList != null) {
                   refresh_token = refreshTokenList.get(0).getValue();
                 }

                 
                 if(access_token.isEmpty() && !refresh_token.isEmpty()) {
                     
                     RestTemplate restTemplate = new RestTemplate();
                     String credentials = client_id + ":" + client_secret;
                     String encodedCredentials = new String(Base64.encode(credentials.getBytes()));

                    HttpHeaders headers = new HttpHeaders();
                    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
                    headers.add("Authorization", "Basic " + encodedCredentials);

                    HttpEntity<String> requestEntity = new HttpEntity<String>(headers);

                    String access_token_url = "http://localhost:8602/oauth/token";
                    access_token_url += "?grant_type=refresh_token";
                    access_token_url += "&refresh_token=" + refresh_token;

                    ResponseEntity<String> aouthResponse = restTemplate.exchange(access_token_url, HttpMethod.POST, requestEntity, String.class);
                    String responseJson = access_token = aouthResponse.getBody();
                    
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode node = null;
                    try {
                        node = mapper.readTree(responseJson);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    
                    String newRefreshToken = node.path("refresh_token").asText();
                    String newAccessToken = node.path("access_token").asText();
                    int expiresIn = Integer.parseInt(node.path("expires_in").asText());
                    int refreshTokenExpireTime = Integer.parseInt(node.path("refreshTokenExpires_In").asText());

                    
                    ResponseCookie accessTokenCookie = ResponseCookie.from("access_token", newAccessToken)
                            .path("/")
                            .maxAge(expiresIn)
                            .build();
                    
                    ResponseCookie refreshTokenCookie = ResponseCookie.from("refresh_token", newRefreshToken)
                            .path("/")
                            .maxAge(refreshTokenExpireTime)
                            .build();
                    
                    response.addCookie(refreshTokenCookie);
                    response.addCookie(accessTokenCookie);
                    
                    access_token = newAccessToken;
                            
                 
                 }else if(refresh_token.isEmpty()){
                     //request.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     response.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
                     response.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     //response.setComplete();
                     return chain.filter(exchange.mutate().request(request).response(response).build());

                 }
                 
                 final String value = access_token;
                 
                 request = request.mutate()
                         .headers(httpHeaders -> httpHeaders.add("Authorization", "Bearer  " + value))
                         .build();
                
                 
             }
             
             return chain.filter(exchange.mutate().request(request).response(response).build());

            
            
        };
    }
    

    public static class Config {

    }
}

已实现此逻辑以检查请求中是否存在刷新令牌。除非它正在重定向 Ui 客户端注销页面(http://localhost:8080/Logout)。

}else if(refresh_token.isEmpty()){
                     //request.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     response.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
                     response.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     //response.setComplete();
                     return chain.filter(exchange.mutate().request(request).response(response).build());

                 }

但是,API 网关级别没有发生请求终止,请求仍在转发到用户微服务。

如何在 apigateway 过滤器处终止请求流并重定向回 ui 客户端注销页面。

标签: javaspring-bootmicroservicesspring-cloud-gateway

解决方案


代替

}else if(refresh_token.isEmpty()){
                     //request.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     response.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
                     response.getHeaders().setLocation(URI.create("http://localhost:8080/Logout"));
                     //response.setComplete();
                     return chain.filter(exchange.mutate().request(request).response(response).build());

             }

重定向用户,使用

}else if(refresh_token.isEmpty()){
    response.setStatusCode(HttpStatus.FOUND); //302
    response
            .getHeaders()
            .set("Location", "/logout");

    return response.setComplete();

                 }

推荐阅读