解决Windows中文乱码问题

master
fengfei 7 years ago
parent 70e3c242de
commit 34cab56437
  1. 112
      pom.xml
  2. 799
      proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java
  3. 331
      proxy-server/src/main/java/org/fengfei/lanproxy/server/config/web/routes/RouteConfig.java
  4. 28
      proxy-server/src/test/resources/config.properties

@ -1,53 +1,59 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fengfei</groupId>
<artifactId>lanproxy</artifactId>
<packaging>pom</packaging>
<version>0.1</version>
<name>lanproxy</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.36.Final</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>proxy-common</module>
<module>proxy-protocol</module>
<module>proxy-server</module>
<module>proxy-client</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fengfei</groupId>
<artifactId>lanproxy</artifactId>
<packaging>pom</packaging>
<version>0.1</version>
<name>lanproxy</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.36.Final</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>proxy-common</module>
<module>proxy-protocol</module>
<module>proxy-server</module>
<module>proxy-client</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,399 +1,400 @@
package org.fengfei.lanproxy.server.config;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.fengfei.lanproxy.common.Config;
import org.fengfei.lanproxy.common.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
/**
* server config
*
* @author fengfei
*
*/
public class ProxyConfig implements Serializable {
private static final long serialVersionUID = 1L;
/** 配置文件为config.json */
public static final String CONFIG_FILE;
private static Logger logger = LoggerFactory.getLogger(ProxyConfig.class);
static {
// 代理配置信息存放在用户根目录下
String dataPath = System.getProperty("user.home") + "/" + ".lanproxy/";
File file = new File(dataPath);
if (!file.isDirectory()) {
file.mkdir();
}
CONFIG_FILE = dataPath + "/config.json";
}
/** 代理服务器绑定主机host */
private String serverBind;
/** 代理服务器与代理客户端通信端口 */
private Integer serverPort;
/** 配置服务绑定主机host */
private String configServerBind;
/** 配置服务端口 */
private Integer configServerPort;
/** 配置服务管理员用户名 */
private String configAdminUsername;
/** 配置服务管理员密码 */
private String configAdminPassword;
/** 代理客户端,支持多个客户端 */
private List<Client> clients;
/** 更新配置后保证在其他线程即时生效 */
private static ProxyConfig instance = new ProxyConfig();;
/** 代理服务器为各个代理客户端(key)开启对应的端口列表(value) */
private volatile Map<String, List<Integer>> clientInetPortMapping = new HashMap<String, List<Integer>>();
/** 代理服务器上的每个对外端口(key)对应的代理客户端背后的真实服务器信息(value) */
private volatile Map<Integer, String> inetPortLanInfoMapping = new HashMap<Integer, String>();
/** 配置变化监听器 */
private List<ConfigChangedListener> configChangedListeners = new ArrayList<ConfigChangedListener>();
private ProxyConfig() {
// 代理服务器主机和端口配置初始化
this.serverPort = Config.getInstance().getIntValue("server.port");
this.serverBind = Config.getInstance().getStringValue("server.bind", "0.0.0.0");
// 配置服务器主机和端口配置初始化
this.configServerPort = Config.getInstance().getIntValue("config.server.port");
this.configServerBind = Config.getInstance().getStringValue("config.server.bind", "0.0.0.0");
// 配置服务器管理员登录认证信息
this.configAdminUsername = Config.getInstance().getStringValue("config.admin.username");
this.configAdminPassword = Config.getInstance().getStringValue("config.admin.password");
logger.info(
"config init serverBind {}, serverPort {}, configServerBind {}, configServerPort {}, configAdminUsername {}, configAdminPassword {}",
serverBind, serverPort, configServerBind, configServerPort, configAdminUsername, configAdminPassword);
update(null);
}
public Integer getServerPort() {
return this.serverPort;
}
public String getServerBind() {
return serverBind;
}
public void setServerBind(String serverBind) {
this.serverBind = serverBind;
}
public String getConfigServerBind() {
return configServerBind;
}
public void setConfigServerBind(String configServerBind) {
this.configServerBind = configServerBind;
}
public Integer getConfigServerPort() {
return configServerPort;
}
public void setConfigServerPort(Integer configServerPort) {
this.configServerPort = configServerPort;
}
public String getConfigAdminUsername() {
return configAdminUsername;
}
public void setConfigAdminUsername(String configAdminUsername) {
this.configAdminUsername = configAdminUsername;
}
public String getConfigAdminPassword() {
return configAdminPassword;
}
public void setConfigAdminPassword(String configAdminPassword) {
this.configAdminPassword = configAdminPassword;
}
public void setServerPort(Integer serverPort) {
this.serverPort = serverPort;
}
public List<Client> getClients() {
return clients;
}
/**
* 解析配置文件
*/
public void update(String proxyMappingConfigJson) {
File file = new File(CONFIG_FILE);
try {
if (proxyMappingConfigJson == null && file.exists()) {
InputStream in = new FileInputStream(file);
byte[] buf = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int readIndex;
while ((readIndex = in.read(buf)) != -1) {
out.write(buf, 0, readIndex);
}
in.close();
proxyMappingConfigJson = new String(out.toByteArray());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
List<Client> clients = JsonUtil.json2object(proxyMappingConfigJson, new TypeToken<List<Client>>() {
});
if (clients == null) {
clients = new ArrayList<Client>();
}
Map<String, List<Integer>> clientInetPortMapping = new HashMap<String, List<Integer>>();
Map<Integer, String> inetPortLanInfoMapping = new HashMap<Integer, String>();
// 构造端口映射关系
for (Client client : clients) {
String clientKey = client.getClientKey();
if (clientInetPortMapping.containsKey(clientKey)) {
throw new IllegalArgumentException("密钥同时作为客户端标识,不能重复: " + clientKey);
}
List<ClientProxyMapping> mappings = client.getProxyMappings();
List<Integer> ports = new ArrayList<Integer>();
clientInetPortMapping.put(clientKey, ports);
for (ClientProxyMapping mapping : mappings) {
Integer port = mapping.getInetPort();
ports.add(port);
if (inetPortLanInfoMapping.containsKey(port)) {
throw new IllegalArgumentException("一个公网端口只能映射一个后端信息,不能重复: " + port);
}
inetPortLanInfoMapping.put(port, mapping.getLan());
}
}
// 替换之前的配置关系
this.clientInetPortMapping = clientInetPortMapping;
this.inetPortLanInfoMapping = inetPortLanInfoMapping;
this.clients = clients;
try {
FileOutputStream out = new FileOutputStream(file);
out.write(proxyMappingConfigJson.getBytes());
out.flush();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
notifyconfigChangedListeners();
}
/**
* 配置更新通知
*/
private void notifyconfigChangedListeners() {
List<ConfigChangedListener> changedListeners = new ArrayList<ConfigChangedListener>(configChangedListeners);
for (ConfigChangedListener changedListener : changedListeners) {
changedListener.onChanged();
}
}
/**
* 添加配置变化监听器
*
* @param configChangedListener
*/
public void addConfigChangedListener(ConfigChangedListener configChangedListener) {
configChangedListeners.add(configChangedListener);
}
/**
* 移除配置变化监听器
*
* @param configChangedListener
*/
public void removeConfigChangedListener(ConfigChangedListener configChangedListener) {
configChangedListeners.remove(configChangedListener);
}
/**
* 获取代理客户端对应的代理服务器端口
*
* @param clientKey
* @return
*/
public List<Integer> getClientInetPorts(String clientKey) {
return clientInetPortMapping.get(clientKey);
}
/**
* 获取所有的clientKey
*
* @return
*/
public Set<String> getClientKeySet() {
return clientInetPortMapping.keySet();
}
/**
* 根据代理服务器端口获取后端服务器代理信息
*
* @param port
* @return
*/
public String getLanInfo(Integer port) {
return inetPortLanInfoMapping.get(port);
}
/**
* 返回需要绑定在代理服务器的端口用于用户请求
*
* @return
*/
public List<Integer> getUserPorts() {
List<Integer> ports = new ArrayList<Integer>();
Iterator<Integer> ite = inetPortLanInfoMapping.keySet().iterator();
while (ite.hasNext()) {
ports.add(ite.next());
}
return ports;
}
public static ProxyConfig getInstance() {
return instance;
}
/**
* 代理客户端
*
* @author fengfei
*
*/
public static class Client implements Serializable {
private static final long serialVersionUID = 1L;
/** 客户端备注名称 */
private String name;
/** 代理客户端唯一标识key */
private String clientKey;
/** 代理客户端与其后面的真实服务器映射关系 */
private List<ClientProxyMapping> proxyMappings;
public String getClientKey() {
return clientKey;
}
public void setClientKey(String clientKey) {
this.clientKey = clientKey;
}
public List<ClientProxyMapping> getProxyMappings() {
return proxyMappings;
}
public void setProxyMappings(List<ClientProxyMapping> proxyMappings) {
this.proxyMappings = proxyMappings;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 代理客户端与其后面真实服务器映射关系
*
* @author fengfei
*
*/
public static class ClientProxyMapping {
/** 代理服务器端口 */
private Integer inetPort;
/** 需要代理的网络信息(代理客户端能够访问),格式 192.168.1.99:80 (必须带端口) */
private String lan;
/** 备注名称 */
private String name;
public Integer getInetPort() {
return inetPort;
}
public void setInetPort(Integer inetPort) {
this.inetPort = inetPort;
}
public String getLan() {
return lan;
}
public void setLan(String lan) {
this.lan = lan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 配置更新回调
*
* @author fengfei
*
*/
public static interface ConfigChangedListener {
void onChanged();
}
}
package org.fengfei.lanproxy.server.config;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.fengfei.lanproxy.common.Config;
import org.fengfei.lanproxy.common.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
/**
* server config
*
* @author fengfei
*
*/
public class ProxyConfig implements Serializable {
private static final long serialVersionUID = 1L;
/** 配置文件为config.json */
public static final String CONFIG_FILE;
private static Logger logger = LoggerFactory.getLogger(ProxyConfig.class);
static {
// 代理配置信息存放在用户根目录下
String dataPath = System.getProperty("user.home") + "/" + ".lanproxy/";
File file = new File(dataPath);
if (!file.isDirectory()) {
file.mkdir();
}
CONFIG_FILE = dataPath + "/config.json";
}
/** 代理服务器绑定主机host */
private String serverBind;
/** 代理服务器与代理客户端通信端口 */
private Integer serverPort;
/** 配置服务绑定主机host */
private String configServerBind;
/** 配置服务端口 */
private Integer configServerPort;
/** 配置服务管理员用户名 */
private String configAdminUsername;
/** 配置服务管理员密码 */
private String configAdminPassword;
/** 代理客户端,支持多个客户端 */
private List<Client> clients;
/** 更新配置后保证在其他线程即时生效 */
private static ProxyConfig instance = new ProxyConfig();;
/** 代理服务器为各个代理客户端(key)开启对应的端口列表(value) */
private volatile Map<String, List<Integer>> clientInetPortMapping = new HashMap<String, List<Integer>>();
/** 代理服务器上的每个对外端口(key)对应的代理客户端背后的真实服务器信息(value) */
private volatile Map<Integer, String> inetPortLanInfoMapping = new HashMap<Integer, String>();
/** 配置变化监听器 */
private List<ConfigChangedListener> configChangedListeners = new ArrayList<ConfigChangedListener>();
private ProxyConfig() {
// 代理服务器主机和端口配置初始化
this.serverPort = Config.getInstance().getIntValue("server.port");
this.serverBind = Config.getInstance().getStringValue("server.bind", "0.0.0.0");
// 配置服务器主机和端口配置初始化
this.configServerPort = Config.getInstance().getIntValue("config.server.port");
this.configServerBind = Config.getInstance().getStringValue("config.server.bind", "0.0.0.0");
// 配置服务器管理员登录认证信息
this.configAdminUsername = Config.getInstance().getStringValue("config.admin.username");
this.configAdminPassword = Config.getInstance().getStringValue("config.admin.password");
logger.info(
"config init serverBind {}, serverPort {}, configServerBind {}, configServerPort {}, configAdminUsername {}, configAdminPassword {}",
serverBind, serverPort, configServerBind, configServerPort, configAdminUsername, configAdminPassword);
update(null);
}
public Integer getServerPort() {
return this.serverPort;
}
public String getServerBind() {
return serverBind;
}
public void setServerBind(String serverBind) {
this.serverBind = serverBind;
}
public String getConfigServerBind() {
return configServerBind;
}
public void setConfigServerBind(String configServerBind) {
this.configServerBind = configServerBind;
}
public Integer getConfigServerPort() {
return configServerPort;
}
public void setConfigServerPort(Integer configServerPort) {
this.configServerPort = configServerPort;
}
public String getConfigAdminUsername() {
return configAdminUsername;
}
public void setConfigAdminUsername(String configAdminUsername) {
this.configAdminUsername = configAdminUsername;
}
public String getConfigAdminPassword() {
return configAdminPassword;
}
public void setConfigAdminPassword(String configAdminPassword) {
this.configAdminPassword = configAdminPassword;
}
public void setServerPort(Integer serverPort) {
this.serverPort = serverPort;
}
public List<Client> getClients() {
return clients;
}
/**
* 解析配置文件
*/
public void update(String proxyMappingConfigJson) {
File file = new File(CONFIG_FILE);
try {
if (proxyMappingConfigJson == null && file.exists()) {
InputStream in = new FileInputStream(file);
byte[] buf = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int readIndex;
while ((readIndex = in.read(buf)) != -1) {
out.write(buf, 0, readIndex);
}
in.close();
proxyMappingConfigJson = new String(out.toByteArray(), Charset.forName("UTF-8"));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
List<Client> clients = JsonUtil.json2object(proxyMappingConfigJson, new TypeToken<List<Client>>() {
});
if (clients == null) {
clients = new ArrayList<Client>();
}
Map<String, List<Integer>> clientInetPortMapping = new HashMap<String, List<Integer>>();
Map<Integer, String> inetPortLanInfoMapping = new HashMap<Integer, String>();
// 构造端口映射关系
for (Client client : clients) {
String clientKey = client.getClientKey();
if (clientInetPortMapping.containsKey(clientKey)) {
throw new IllegalArgumentException("密钥同时作为客户端标识,不能重复: " + clientKey);
}
List<ClientProxyMapping> mappings = client.getProxyMappings();
List<Integer> ports = new ArrayList<Integer>();
clientInetPortMapping.put(clientKey, ports);
for (ClientProxyMapping mapping : mappings) {
Integer port = mapping.getInetPort();
ports.add(port);
if (inetPortLanInfoMapping.containsKey(port)) {
throw new IllegalArgumentException("一个公网端口只能映射一个后端信息,不能重复: " + port);
}
inetPortLanInfoMapping.put(port, mapping.getLan());
}
}
// 替换之前的配置关系
this.clientInetPortMapping = clientInetPortMapping;
this.inetPortLanInfoMapping = inetPortLanInfoMapping;
this.clients = clients;
try {
FileOutputStream out = new FileOutputStream(file);
out.write(proxyMappingConfigJson.getBytes(Charset.forName("UTF-8")));
out.flush();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
notifyconfigChangedListeners();
}
/**
* 配置更新通知
*/
private void notifyconfigChangedListeners() {
List<ConfigChangedListener> changedListeners = new ArrayList<ConfigChangedListener>(configChangedListeners);
for (ConfigChangedListener changedListener : changedListeners) {
changedListener.onChanged();
}
}
/**
* 添加配置变化监听器
*
* @param configChangedListener
*/
public void addConfigChangedListener(ConfigChangedListener configChangedListener) {
configChangedListeners.add(configChangedListener);
}
/**
* 移除配置变化监听器
*
* @param configChangedListener
*/
public void removeConfigChangedListener(ConfigChangedListener configChangedListener) {
configChangedListeners.remove(configChangedListener);
}
/**
* 获取代理客户端对应的代理服务器端口
*
* @param clientKey
* @return
*/
public List<Integer> getClientInetPorts(String clientKey) {
return clientInetPortMapping.get(clientKey);
}
/**
* 获取所有的clientKey
*
* @return
*/
public Set<String> getClientKeySet() {
return clientInetPortMapping.keySet();
}
/**
* 根据代理服务器端口获取后端服务器代理信息
*
* @param port
* @return
*/
public String getLanInfo(Integer port) {
return inetPortLanInfoMapping.get(port);
}
/**
* 返回需要绑定在代理服务器的端口用于用户请求
*
* @return
*/
public List<Integer> getUserPorts() {
List<Integer> ports = new ArrayList<Integer>();
Iterator<Integer> ite = inetPortLanInfoMapping.keySet().iterator();
while (ite.hasNext()) {
ports.add(ite.next());
}
return ports;
}
public static ProxyConfig getInstance() {
return instance;
}
/**
* 代理客户端
*
* @author fengfei
*
*/
public static class Client implements Serializable {
private static final long serialVersionUID = 1L;
/** 客户端备注名称 */
private String name;
/** 代理客户端唯一标识key */
private String clientKey;
/** 代理客户端与其后面的真实服务器映射关系 */
private List<ClientProxyMapping> proxyMappings;
public String getClientKey() {
return clientKey;
}
public void setClientKey(String clientKey) {
this.clientKey = clientKey;
}
public List<ClientProxyMapping> getProxyMappings() {
return proxyMappings;
}
public void setProxyMappings(List<ClientProxyMapping> proxyMappings) {
this.proxyMappings = proxyMappings;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 代理客户端与其后面真实服务器映射关系
*
* @author fengfei
*
*/
public static class ClientProxyMapping {
/** 代理服务器端口 */
private Integer inetPort;
/** 需要代理的网络信息(代理客户端能够访问),格式 192.168.1.99:80 (必须带端口) */
private String lan;
/** 备注名称 */
private String name;
public Integer getInetPort() {
return inetPort;
}
public void setInetPort(Integer inetPort) {
this.inetPort = inetPort;
}
public String getLan() {
return lan;
}
public void setLan(String lan) {
this.lan = lan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 配置更新回调
*
* @author fengfei
*
*/
public static interface ConfigChangedListener {
void onChanged();
}
}

@ -1,164 +1,167 @@
package org.fengfei.lanproxy.server.config.web.routes;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.fengfei.lanproxy.common.JsonUtil;
import org.fengfei.lanproxy.server.config.ProxyConfig;
import org.fengfei.lanproxy.server.config.ProxyConfig.Client;
import org.fengfei.lanproxy.server.config.web.ApiRoute;
import org.fengfei.lanproxy.server.config.web.RequestHandler;
import org.fengfei.lanproxy.server.config.web.RequestMiddleware;
import org.fengfei.lanproxy.server.config.web.ResponseInfo;
import org.fengfei.lanproxy.server.config.web.exception.ContextException;
import org.fengfei.lanproxy.server.metrics.MetricsCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
/**
* 接口实现
*
* @author fengfei
*
*/
public class RouteConfig {
protected static final String AUTH_COOKIE_KEY = "token";
private static Logger logger = LoggerFactory.getLogger(RouteConfig.class);
/** 管理员不能同时在多个地方登录 */
private static String token;
public static void init() {
ApiRoute.addMiddleware(new RequestMiddleware() {
@Override
public void preRequest(FullHttpRequest request) {
String cookieHeader = request.headers().get(HttpHeaders.Names.COOKIE);
boolean authenticated = false;
if (cookieHeader != null) {
String[] cookies = cookieHeader.split(";");
for (String cookie : cookies) {
String[] cookieArr = cookie.split("=");
if (AUTH_COOKIE_KEY.equals(cookieArr[0].trim())) {
if (cookieArr.length == 2 && cookieArr[1].equals(token)) {
authenticated = true;
}
}
}
}
String auth = request.headers().get(HttpHeaders.Names.AUTHORIZATION);
if (!authenticated && auth != null) {
String[] authArr = auth.split(" ");
if (authArr.length == 2 && authArr[0].equals(ProxyConfig.getInstance().getConfigAdminUsername()) && authArr[1].equals(ProxyConfig.getInstance().getConfigAdminPassword())) {
authenticated = true;
}
}
if (!request.getUri().equals("/login") && !authenticated) {
throw new ContextException(ResponseInfo.CODE_UNAUTHORIZED);
}
logger.info("handle request for api {}", request.getUri());
}
});
// 获取配置详细信息
ApiRoute.addRoute("/config/detail", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(ProxyConfig.getInstance().getClients());
}
});
// 更新配置
ApiRoute.addRoute("/config/update", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
byte[] buf = new byte[request.content().readableBytes()];
request.content().readBytes(buf);
String config = new String(buf);
List<Client> clients = JsonUtil.json2object(config, new TypeToken<List<Client>>() {
});
if (clients == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error json config");
}
try {
ProxyConfig.getInstance().update(config);
} catch (Exception ex) {
logger.error("config update error", ex);
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, ex.getMessage());
}
return ResponseInfo.build(ResponseInfo.CODE_OK, "success");
}
});
ApiRoute.addRoute("/login", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
byte[] buf = new byte[request.content().readableBytes()];
request.content().readBytes(buf);
String config = new String(buf);
Map<String, String> loginParams = JsonUtil.json2object(config, new TypeToken<Map<String, String>>() {
});
if (loginParams == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error login info");
}
String username = loginParams.get("username");
String password = loginParams.get("password");
if (username == null || password == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error username or password");
}
if (username.equals(ProxyConfig.getInstance().getConfigAdminUsername()) && password.equals(ProxyConfig.getInstance().getConfigAdminPassword())) {
token = UUID.randomUUID().toString().replace("-", "");
return ResponseInfo.build(token);
}
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error username or password");
}
});
ApiRoute.addRoute("/logout", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
token = null;
return ResponseInfo.build(ResponseInfo.CODE_OK, "success");
}
});
ApiRoute.addRoute("/metrics/get", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(MetricsCollector.getAllMetrics());
}
});
ApiRoute.addRoute("/metrics/getandreset", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(MetricsCollector.getAndResetAllMetrics());
}
});
}
}
package org.fengfei.lanproxy.server.config.web.routes;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.fengfei.lanproxy.common.JsonUtil;
import org.fengfei.lanproxy.server.config.ProxyConfig;
import org.fengfei.lanproxy.server.config.ProxyConfig.Client;
import org.fengfei.lanproxy.server.config.web.ApiRoute;
import org.fengfei.lanproxy.server.config.web.RequestHandler;
import org.fengfei.lanproxy.server.config.web.RequestMiddleware;
import org.fengfei.lanproxy.server.config.web.ResponseInfo;
import org.fengfei.lanproxy.server.config.web.exception.ContextException;
import org.fengfei.lanproxy.server.metrics.MetricsCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
/**
* 接口实现
*
* @author fengfei
*
*/
public class RouteConfig {
protected static final String AUTH_COOKIE_KEY = "token";
private static Logger logger = LoggerFactory.getLogger(RouteConfig.class);
/** 管理员不能同时在多个地方登录 */
private static String token;
public static void init() {
ApiRoute.addMiddleware(new RequestMiddleware() {
@Override
public void preRequest(FullHttpRequest request) {
String cookieHeader = request.headers().get(HttpHeaders.Names.COOKIE);
boolean authenticated = false;
if (cookieHeader != null) {
String[] cookies = cookieHeader.split(";");
for (String cookie : cookies) {
String[] cookieArr = cookie.split("=");
if (AUTH_COOKIE_KEY.equals(cookieArr[0].trim())) {
if (cookieArr.length == 2 && cookieArr[1].equals(token)) {
authenticated = true;
}
}
}
}
String auth = request.headers().get(HttpHeaders.Names.AUTHORIZATION);
if (!authenticated && auth != null) {
String[] authArr = auth.split(" ");
if (authArr.length == 2 && authArr[0].equals(ProxyConfig.getInstance().getConfigAdminUsername())
&& authArr[1].equals(ProxyConfig.getInstance().getConfigAdminPassword())) {
authenticated = true;
}
}
if (!request.getUri().equals("/login") && !authenticated) {
throw new ContextException(ResponseInfo.CODE_UNAUTHORIZED);
}
logger.info("handle request for api {}", request.getUri());
}
});
// 获取配置详细信息
ApiRoute.addRoute("/config/detail", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(ProxyConfig.getInstance().getClients());
}
});
// 更新配置
ApiRoute.addRoute("/config/update", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
byte[] buf = new byte[request.content().readableBytes()];
request.content().readBytes(buf);
String config = new String(buf, Charset.forName("UTF-8"));
List<Client> clients = JsonUtil.json2object(config, new TypeToken<List<Client>>() {
});
if (clients == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error json config");
}
try {
ProxyConfig.getInstance().update(config);
} catch (Exception ex) {
logger.error("config update error", ex);
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, ex.getMessage());
}
return ResponseInfo.build(ResponseInfo.CODE_OK, "success");
}
});
ApiRoute.addRoute("/login", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
byte[] buf = new byte[request.content().readableBytes()];
request.content().readBytes(buf);
String config = new String(buf);
Map<String, String> loginParams = JsonUtil.json2object(config, new TypeToken<Map<String, String>>() {
});
if (loginParams == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error login info");
}
String username = loginParams.get("username");
String password = loginParams.get("password");
if (username == null || password == null) {
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error username or password");
}
if (username.equals(ProxyConfig.getInstance().getConfigAdminUsername())
&& password.equals(ProxyConfig.getInstance().getConfigAdminPassword())) {
token = UUID.randomUUID().toString().replace("-", "");
return ResponseInfo.build(token);
}
return ResponseInfo.build(ResponseInfo.CODE_INVILID_PARAMS, "Error username or password");
}
});
ApiRoute.addRoute("/logout", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
token = null;
return ResponseInfo.build(ResponseInfo.CODE_OK, "success");
}
});
ApiRoute.addRoute("/metrics/get", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(MetricsCollector.getAllMetrics());
}
});
ApiRoute.addRoute("/metrics/getandreset", new RequestHandler() {
@Override
public ResponseInfo request(FullHttpRequest request) {
return ResponseInfo.build(MetricsCollector.getAndResetAllMetrics());
}
});
}
}

@ -1,15 +1,15 @@
server.bind=0.0.0.0
server.port=4900
server.ssl.enable=true
server.ssl.bind=0.0.0.0
server.ssl.port=4993
server.ssl.jksPath=test.jks
server.ssl.keyStorePassword=123456
server.ssl.keyManagerPassword=123456
server.ssl.needsClientAuth=false
config.server.bind=0.0.0.0
config.server.port=8082
config.admin.username=admin
server.bind=0.0.0.0
server.port=4900
server.ssl.enable=true
server.ssl.bind=0.0.0.0
server.ssl.port=4993
server.ssl.jksPath=test.jks
server.ssl.keyStorePassword=123456
server.ssl.keyManagerPassword=123456
server.ssl.needsClientAuth=false
config.server.bind=0.0.0.0
config.server.port=8090
config.admin.username=admin
config.admin.password=admin
Loading…
Cancel
Save