/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved.
 * <a>http://www.crunii.com</a>
 */
package com.crunii.micro.gateway.filter;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Base64;

/**
 * @author shenhs create 2023/6/6 21:06
 */
@Component
@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true")
public class SwaggerAuthGatewayFilter implements WebFilter,Ordered {

	@Value("${swagger.userName}")
	private String USERNAME;
	@Value("${swagger.password}")
	private String PASSWORD;

	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE-1;
	}

/*
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		String path = exchange.getRequest().getPath().toString();
		if (path.contains("swagger") || path.contains("v2/api-docs")) {
			HttpHeaders headers = exchange.getRequest().getHeaders();
			String authorization = headers.getFirst(HttpHeaders.AUTHORIZATION);
			if (StringUtils.isEmpty(authorization)) {
				// 认证失败
				exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
				return exchange.getResponse().setComplete();
			}
			if (!checkAuthorization(authorization)) {
				// 认证失败
				exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
				return exchange.getResponse().setComplete();
			}
			// 添加认证信息
			ServerHttpRequest request = exchange.getRequest().mutate()
					.header(HttpHeaders.AUTHORIZATION, authorization)
					.build();
			ServerWebExchange authExchange = exchange.mutate().request(request).build();
			return chain.filter(authExchange);
		}
		return chain.filter(exchange);
	}
*/
	private boolean checkAuthorization(String authorization) {
		if (authorization == null) {
			return false;
		}
		String[] split = authorization.split(" ");
		if (split.length != 2) {
			return false;
		}
		String base64 = split[1];
		String auth = new String(Base64.getDecoder().decode(base64));
		String[] userAndPass = auth.split(":");
		if (userAndPass.length != 2) {
			return false;
		}
		return userAndPass[0].equals(USERNAME) && userAndPass[1].equals(PASSWORD);
	}

	@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
		String path = exchange.getRequest().getPath().toString();
		if (path.contains("swagger") || path.contains("v2/api-docs")) {
			HttpHeaders headers = exchange.getRequest().getHeaders();
			String authorization = headers.getFirst(HttpHeaders.AUTHORIZATION);
			if (StringUtils.isEmpty(authorization)) {
				// 认证失败
				exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
				exchange.getResponse().getHeaders().add(HttpHeaders.WWW_AUTHENTICATE,"Basic realm=\"请输入用户名密码\"");
				return exchange.getResponse().setComplete();
			}
			if (!checkAuthorization(authorization)) {
				// 认证失败
				exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
				return exchange.getResponse().setComplete();
			}
			// 添加认证信息
			ServerHttpRequest request = exchange.getRequest().mutate()
					.header(HttpHeaders.AUTHORIZATION, authorization)
					.build();
			ServerWebExchange authExchange = exchange.mutate().request(request).build();
			return chain.filter(authExchange);
		}
		return chain.filter(exchange);
	}
}
