├── .gitignore
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── Dockerfile
├── README.md
├── desgin.md
├── docker
├── application.properties
├── forward_db.mv.db
└── forward_db.trace.db
├── forward_db.mv.db
├── forward_db.trace.db
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── leeroy
│ │ └── forwordpanel
│ │ └── forwordpanel
│ │ ├── ForwordpanelApplication.java
│ │ ├── common
│ │ ├── AuthInterceptor.java
│ │ ├── GlobalExceptionHandler.java
│ │ ├── IStatusMessage.java
│ │ ├── RestResult.java
│ │ ├── WebCurrentData.java
│ │ ├── WebException.java
│ │ ├── WebThreadLocalManager.java
│ │ ├── annotation
│ │ │ ├── FieldAuth.java
│ │ │ ├── NoAuth.java
│ │ │ ├── NoIp.java
│ │ │ └── NoLogin.java
│ │ ├── config
│ │ │ ├── SpringFoxConfig.java
│ │ │ └── WebMvcConfig.java
│ │ ├── enums
│ │ │ ├── ForwardStatusEnum.java
│ │ │ └── ServerStatusEnum.java
│ │ ├── response
│ │ │ ├── ApiResponse.java
│ │ │ ├── PageDataResult.java
│ │ │ └── ResponseResult.java
│ │ └── util
│ │ │ ├── BeanCopyUtil.java
│ │ │ ├── BeanCopyUtilCallBack.java
│ │ │ ├── CertUtil.java
│ │ │ ├── DateUtils.java
│ │ │ ├── DigestUtils.java
│ │ │ ├── IpUtil.java
│ │ │ ├── ShellUtil.java
│ │ │ ├── SimpleForward.java
│ │ │ ├── TokenUtil.java
│ │ │ └── remotessh
│ │ │ ├── KeyLoginUserInfo.java
│ │ │ ├── MyUserInfo.java
│ │ │ └── SSHCommandExecutor.java
│ │ ├── controller
│ │ ├── ConfigController.java
│ │ ├── IndexController.java
│ │ ├── LoginController.java
│ │ ├── PortController.java
│ │ ├── ResourceController.java
│ │ ├── ServerController.java
│ │ ├── SysConfigController.java
│ │ ├── SystemController.java
│ │ ├── UserController.java
│ │ ├── UserPortController.java
│ │ └── UserPortForwardController.java
│ │ ├── dao
│ │ ├── ClashDao.java
│ │ ├── ForwardFlowDao.java
│ │ ├── PortDao.java
│ │ ├── ServerDao.java
│ │ ├── SysConfigDao.java
│ │ ├── UserDao.java
│ │ ├── UserPortDao.java
│ │ ├── UserPortForwardDao.java
│ │ ├── UserServerDao.java
│ │ └── UserTokenDao.java
│ │ ├── dto
│ │ ├── ClashNodeBase.java
│ │ ├── ClashNodeTrojan.java
│ │ ├── DataFlow.java
│ │ ├── ForwardFlowDTO.java
│ │ ├── LoginDTO.java
│ │ ├── PageRequest.java
│ │ ├── PortAddDTO.java
│ │ ├── PortDTO.java
│ │ ├── PortPageRequest.java
│ │ ├── UserDTO.java
│ │ ├── UserPortDTO.java
│ │ ├── UserPortForwardDTO.java
│ │ ├── UserPortForwardPageReq.java
│ │ ├── UserPortPageRequest.java
│ │ └── UserSearchDTO.java
│ │ ├── job
│ │ ├── CheckDDNSJob.java
│ │ ├── CheckExpireJob.java
│ │ ├── DataUsageJob.java
│ │ └── KeepForwardJob.java
│ │ ├── jpa
│ │ ├── ForwardFlowRepository.java
│ │ ├── PortRepository.java
│ │ ├── ServerRepository.java
│ │ ├── SysConfigRepository.java
│ │ ├── UserPortForwardRepository.java
│ │ ├── UserPortRepository.java
│ │ ├── UserRepository.java
│ │ └── UserServerRepository.java
│ │ ├── model
│ │ ├── Clash.java
│ │ ├── ForwardFlow.java
│ │ ├── Port.java
│ │ ├── Resource.java
│ │ ├── Server.java
│ │ ├── SysConfig.java
│ │ ├── User.java
│ │ ├── UserPort.java
│ │ ├── UserPortForward.java
│ │ ├── UserServer.java
│ │ └── UserToken.java
│ │ └── service
│ │ ├── ConfigService.java
│ │ ├── DataUpgradeService.java
│ │ ├── ForwardFlowService.java
│ │ ├── ForwardService.java
│ │ ├── LoginService.java
│ │ ├── PortService.java
│ │ ├── RemoteForwardService.java
│ │ ├── ServerService.java
│ │ ├── SysConfigService.java
│ │ ├── UserPortForwardService.java
│ │ ├── UserPortService.java
│ │ ├── UserService.java
│ │ └── UserTokenService.java
└── resources
│ ├── application.properties
│ ├── data.sql
│ ├── scripts
│ └── turnOnNat.sh
│ └── static
│ ├── avatar.gif
│ ├── favicon.ico
│ ├── favicon.png
│ ├── index.html
│ ├── reward.gif
│ ├── static
│ ├── css
│ │ ├── app.cd5c539b.css
│ │ ├── chunk-22fe9ae1.d62c05ee.css
│ │ ├── chunk-2d423526.e6231e8e.css
│ │ ├── chunk-480b22f6.a41dcdae.css
│ │ ├── chunk-4c26ca85.31d18062.css
│ │ ├── chunk-632b8606.9ca93816.css
│ │ ├── chunk-76cac56b.fcf8ba06.css
│ │ ├── chunk-76cea4de.3c7f5ad9.css
│ │ ├── chunk-9fdcb8cc.e86064da.css
│ │ ├── chunk-a2c7894a.dc547638.css
│ │ ├── chunk-e732e32c.1a2a53c6.css
│ │ ├── chunk-elementUI.68c70ad5.css
│ │ └── chunk-libs.3dfb7769.css
│ ├── fonts
│ │ ├── element-icons.535877f5.woff
│ │ └── element-icons.732389de.ttf
│ ├── img
│ │ ├── 404.a57b6f31.png
│ │ └── 404_cloud.0f4bc32b.png
│ └── js
│ │ ├── app.c13641de.js
│ │ ├── chunk-22fe9ae1.8c49d34d.js
│ │ ├── chunk-2d423526.31af6728.js
│ │ ├── chunk-397133d0.8e76ca20.js
│ │ ├── chunk-480b22f6.4f228d1f.js
│ │ ├── chunk-4c26ca85.00e82d61.js
│ │ ├── chunk-632b8606.5ee39ba4.js
│ │ ├── chunk-6474e2f4.44dee973.js
│ │ ├── chunk-76cac56b.8ccb935e.js
│ │ ├── chunk-76cea4de.78bea551.js
│ │ ├── chunk-9fdcb8cc.b71478a3.js
│ │ ├── chunk-a2c7894a.13b2fea3.js
│ │ ├── chunk-e732e32c.36ae8557.js
│ │ ├── chunk-elementUI.a450811c.js
│ │ └── chunk-libs.d21abeae.js
│ └── usdt.jpeg
└── test
└── java
└── com
└── leeroy
└── forwordpanel
└── forwordpanel
├── ForwordpanelApplicationTests.java
├── MyUserInfo.java
└── SSHCommandExecutor.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 | src/main/resources/static/.DS_Store
7 | forward_db.mv.db
8 | forward_db.mv.db.trace.db
9 |
10 | ### STS ###
11 | .apt_generated
12 | .classpath
13 | .factorypath
14 | .project
15 | .settings
16 | .springBeans
17 | .sts4-cache
18 |
19 | ### IntelliJ IDEA ###
20 | .idea
21 | *.iws
22 | *.iml
23 | *.ipr
24 |
25 | ### NetBeans ###
26 | /nbproject/private/
27 | /nbbuild/
28 | /dist/
29 | /nbdist/
30 | /.nb-gradle/
31 | build/
32 |
33 | ### VS Code ###
34 | .vscode/
35 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.6";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | ADD target/forwordpanel-1.0.5-SNAPSHOT.jar app.jar
4 | ADD docker/forward_db.mv.db forward_db.mv.db
5 | ADD docker/forward_db.trace.db forward_db.trace.db
6 | COPY docker/application.properties application.properties
7 | ENTRYPOINT ["java","-jar","/app.jar"]
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 闲(的)蛋(疼)中转面板
2 | 一个轻量的中转面板, 一台面板管理多台中转机器, 实现出租, 限流, 转发等功能
3 |
4 | 介绍见wiki: https://github.com/xiaoli123/forwordpanel/wiki
5 |
6 | 基于Java编写的中转管理平台(中转面板)
7 | 使用的技术:
8 | - springboot
9 | - element-ui
10 | - h2
11 |
12 | > 注意, 系统不必每个nat上都部署, 也不需要一定要部署在nat, 只要部署的机器能ssh上nat即可, 部署一套系统管理多个nat
13 |
14 |
15 |
16 | ## 主要功能
17 | 集中管理中转机器, 出租, 限流, 到期禁用等等, 具体见wiki:
18 | https://github.com/xiaoli123/forwordpanel/wiki
19 |
20 | ## 使用方式
21 | 见wiki: https://github.com/xiaoli123/forwordpanel/wiki
22 |
23 |
24 |
--------------------------------------------------------------------------------
/desgin.md:
--------------------------------------------------------------------------------
1 | # 功能
2 |
3 | ### 2020-09-20
4 | - 修复流量MB展示问题
5 | - 用户流量总量统计
6 | - 流量限制
7 | - 流量重置
8 |
--------------------------------------------------------------------------------
/docker/application.properties:
--------------------------------------------------------------------------------
1 | #���þ�̬��Դ·��������Զ��ŷָ�
2 | server.port=8080
3 | spring.resources.static-locations= classpath:static/,file:static/
4 | spring.datasource.url=jdbc:h2:./forward_db;DB_CLOSE_ON_EXIT=FALSE
5 | spring.datasource.driverClassName=org.h2.Driver
6 | spring.datasource.username=sa
7 | spring.datasource.password=*yBHJHud$f45fgf
8 | # H2
9 | spring.h2.console.enabled=true
10 | spring.h2.console.path=/h2
11 | spring.h2.console.settings.web-allow-others=true
12 | spring.jpa.generate-ddl=false
13 | spring.jpa.show-sql=true
14 | spring.jpa.hibernate.ddl-auto=update
15 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
16 | panel.version=1.0.5-SNAPSHOT
17 | spring.servlet.multipart.max-file-size=1024MB
18 | spring.servlet.multipart.max-request-size=1024MB
19 |
20 | #mybatis-plus配置控制台打印完整带参数SQL语句
21 | #mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
22 | #mybatis-plus.configuration.map-underscore-to-camel-case=true
23 | panel.default-password=XDZZ@123
24 | ssh.privateKeyPath=D:\\id_rsa_old
25 |
--------------------------------------------------------------------------------
/docker/forward_db.mv.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/docker/forward_db.mv.db
--------------------------------------------------------------------------------
/forward_db.mv.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/forward_db.mv.db
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.1.RELEASE
9 |
10 |
11 | com.leeroy.forwordpanel
12 | forwordpanel
13 | 1.0.5-SNAPSHOT
14 | forwordpanel
15 | port forword panel
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-web
25 |
26 |
27 | dnsjava
28 | dnsjava
29 | 2.1.1
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-devtools
34 | runtime
35 | true
36 |
37 |
38 | com.h2database
39 | h2
40 | runtime
41 |
42 |
43 | org.apache.commons
44 | commons-lang3
45 |
46 |
47 | commons-codec
48 | commons-codec
49 |
50 |
51 | com.baomidou
52 | mybatis-plus-boot-starter
53 | 3.3.2
54 |
55 |
56 | com.github.pagehelper
57 | pagehelper-spring-boot-starter
58 | 1.2.12
59 |
60 |
61 | org.mybatis
62 | mybatis
63 |
64 |
65 | org.mybatis
66 | mybatis-spring
67 |
68 |
69 |
70 |
71 | org.projectlombok
72 | lombok
73 | true
74 |
75 |
76 | io.springfox
77 | springfox-swagger2
78 | 2.9.2
79 |
80 |
81 | io.springfox
82 | springfox-swagger-ui
83 | 2.9.2
84 |
85 |
86 | com.jcraft
87 | jsch
88 | 0.1.55
89 |
90 |
91 | com.alibaba
92 | fastjson
93 | 1.2.68
94 |
95 |
96 | org.springframework.boot
97 | spring-boot-starter-test
98 | test
99 |
100 |
101 | org.junit.vintage
102 | junit-vintage-engine
103 |
104 |
105 |
106 |
107 | org.apache.commons
108 | commons-io
109 | 1.3.2
110 |
111 |
112 | org.springframework.boot
113 | spring-boot-starter-data-jpa
114 |
115 |
116 | org.yaml
117 | snakeyaml
118 |
119 |
120 |
121 |
122 |
123 | docker/application.properties
124 |
125 |
126 |
127 | docker
128 | true
129 |
130 |
131 | src/main/resources
132 | false
133 |
134 |
135 |
136 |
137 | org.springframework.boot
138 | spring-boot-maven-plugin
139 |
140 |
141 | com.spotify
142 | docker-maven-plugin
143 | 1.2.1
144 |
145 |
146 | build-image
147 | package
148 |
149 | build
150 |
151 |
152 |
153 |
154 |
155 | leeroydocker/${project.artifactId}
156 |
157 | ${project.version}
158 |
159 | true
160 | ${project.basedir}
161 |
162 |
163 | /
164 | ${project.build.directory}
165 | ${project.build.finalName}.jar
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/ForwordpanelApplication.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.boot.autoconfigure.domain.EntityScan;
7 | import org.springframework.context.annotation.ComponentScan;
8 |
9 | @SpringBootApplication
10 | @MapperScan("com.leeroy.forwordpanel.forwordpanel.dao")
11 | public class ForwordpanelApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(ForwordpanelApplication.class, args);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/AuthInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.common.util.CertUtil;
6 | import com.leeroy.forwordpanel.forwordpanel.common.util.TokenUtil;
7 | import com.leeroy.forwordpanel.forwordpanel.dao.UserDao;
8 | import com.leeroy.forwordpanel.forwordpanel.model.User;
9 | import com.leeroy.forwordpanel.forwordpanel.model.UserToken;
10 | import com.leeroy.forwordpanel.forwordpanel.service.UserTokenService;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.apache.commons.lang3.StringUtils;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
16 |
17 | import javax.servlet.http.HttpServletRequest;
18 | import javax.servlet.http.HttpServletResponse;
19 | import java.io.IOException;
20 | import java.io.PrintWriter;
21 | import java.util.Objects;
22 |
23 | @Component
24 | @Slf4j
25 | public class AuthInterceptor extends HandlerInterceptorAdapter {
26 |
27 | @Autowired
28 | private UserTokenService userTokenService;
29 |
30 | @Autowired
31 | private UserDao userDao;
32 |
33 | @Override
34 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
35 | log.info(">>>>>>>>>>>>>>>登录验证 {}", request.getRequestURI());
36 | if (CertUtil.checkNoLogin(handler)) {
37 | return true;
38 | }
39 | log.info(">>>>>>>>>>>>>>>权限验证 {}", request.getRequestURI());
40 | // 验证权限
41 | if (CertUtil.checkNoAuth(handler)) {
42 | return true;
43 | }
44 | String token = TokenUtil.getToken(request);
45 | if (StringUtils.isEmpty(token)) {
46 | renderResponse(response, "403", "登录超时, 请重新登录");
47 | return false;
48 | //todo 跳转到登录
49 | }
50 | //根据token获取用户信息
51 | UserToken userToken = userTokenService.getUserToken(token);
52 | if (Objects.isNull(userToken) || userToken.getUserId() == null) {
53 | //todo 跳转到登录页面
54 | renderResponse(response, "403", "登录超时, 请重新登录");
55 | return false;
56 | }
57 | userToken.setExpireTime(userToken.getExpireTime()+1000*60*30);
58 | userTokenService.updateUserToken(userToken);
59 | //当前用户
60 | User user = userDao.selectById(userToken.getUserId());
61 | WebCurrentData.setUser(user);
62 | WebCurrentData.setUserId(user.getId());
63 | WebCurrentData.setUserName(user.getUsername());
64 | return true;
65 | }
66 |
67 |
68 | /**
69 | * ajax响应
70 | *
71 | * @param response
72 | * @param code
73 | * @param msg
74 | */
75 | private void renderResponse(HttpServletResponse response, String code, String msg) {
76 | ApiResponse baseResponse = ApiResponse.error(code, msg);
77 | response.setContentType("application/json;charset=UTF-8");
78 | response.setHeader("Pragma", "No-cache");
79 | response.setHeader("Cache-Control", "no-cache");
80 | response.setDateHeader("Expires", 0);
81 | PrintWriter pWriter = null;
82 | try {
83 | pWriter = response.getWriter();
84 | pWriter.write(JSON.toJSONString(baseResponse));
85 | pWriter.flush();
86 | } catch (IOException e) {
87 | e.getMessage();
88 | } finally {
89 | pWriter.close();
90 | }
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.annotation.ControllerAdvice;
6 | import org.springframework.web.bind.annotation.ExceptionHandler;
7 | import org.springframework.web.bind.annotation.ResponseBody;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 |
11 | @Slf4j
12 | @ControllerAdvice
13 | public class GlobalExceptionHandler {
14 |
15 | @ExceptionHandler(value = Exception.class)
16 | @ResponseBody
17 | public ApiResponse defaultErrorHandler(HttpServletRequest req, Exception e) {
18 | if (e instanceof WebException) {
19 | return ApiResponse.error(((WebException) e).getErrorCode(), ((WebException) e).getErrorMsg());
20 | }
21 | log.error(">>>>>>>>>>>>>>GlobalExceptionHandler catch exception {}", e);
22 | return ApiResponse.error("500", "操作失败");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/IStatusMessage.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | /**
4 | * @Title: IStatusMessage
5 | * @Description: 响应状态信息
6 | * @author: youqing
7 | * @version: 1.0
8 | * @date: 2018/11/23 9:50
9 | */
10 | public interface IStatusMessage {
11 |
12 | String getCode();
13 |
14 | String getMessage();
15 |
16 | public enum SystemStatus implements IStatusMessage{
17 |
18 | SUCCESS("0","SUCCESS"), //请求成功
19 | ERROR("404","ERROR"), //请求失败
20 | PARAM_ERROR("1002","PARAM_ERROR"), //请求参数有误
21 | SUCCESS_MATCH("1003","SUCCESS_MATCH"), //表示成功匹配
22 | NO_LOGIN("1100","NO_LOGIN"), //未登录
23 | MANY_LOGINS("1101","MANY_LOGINS"), //多用户在线(踢出用户)
24 | UPDATE("1102","UPDATE"), //用户信息或权限已更新(退出重新登录)
25 | LOCK("1111","LOCK"); //用户已锁定
26 | private String code;
27 | private String message;
28 |
29 | private SystemStatus(String code,String message){
30 | this.code = code;
31 | this.message = message;
32 | }
33 |
34 | public String getCode(){
35 | return this.code;
36 | }
37 |
38 | public String getMessage(){
39 | return this.message;
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/RestResult.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | @AllArgsConstructor
7 | @Data
8 | public class RestResult {
9 |
10 | private Boolean success;
11 |
12 | private String message;
13 |
14 | public static RestResult success() {
15 | return new RestResult(true, "");
16 | }
17 |
18 | public static RestResult success(String data) {
19 | return new RestResult(true, data);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/WebCurrentData.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.User;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 |
8 | import java.io.Serializable;
9 |
10 | @Builder
11 | @Getter
12 | @Setter
13 | public class WebCurrentData implements Serializable {
14 |
15 | private User user;
16 | private Integer userId;
17 | private String userName;
18 | private String ip;
19 |
20 | public static User getUser() {
21 | return WebThreadLocalManager.get().user;
22 | }
23 |
24 |
25 | public static WebCurrentData setUser(User user) {
26 | WebCurrentData currentData = WebThreadLocalManager.get();
27 | currentData.user = user;
28 | setUserId(user.getId());
29 | setUserName(user.getUsername());
30 | return currentData;
31 | }
32 |
33 |
34 | public static String getUserName() {
35 | return WebThreadLocalManager.get().userName;
36 | }
37 |
38 | public static WebCurrentData setUserName(String userName) {
39 | WebCurrentData currentData = WebThreadLocalManager.get();
40 | currentData.userName = userName;
41 | return currentData;
42 | }
43 |
44 | public static Integer getUserId() {
45 | return WebThreadLocalManager.get().userId;
46 | }
47 |
48 | public static WebCurrentData setUserId(Integer userId) {
49 | WebCurrentData currentData = WebThreadLocalManager.get();
50 | currentData.userId = userId;
51 | return currentData;
52 | }
53 |
54 | public static String getIp() {
55 | return WebThreadLocalManager.get().ip;
56 | }
57 |
58 | private static WebCurrentData setIp(String ip) {
59 | WebCurrentData currentData = WebThreadLocalManager.get();
60 | currentData.ip = ip;
61 | return currentData;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/WebException.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | /**
8 | * @Author: meishaoyong
9 | * @Date: 2019/8/28 10:58
10 | * @Description:
11 | */
12 |
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class WebException extends RuntimeException {
17 |
18 | private static final long serialVersionUID = 1L;
19 | private Object errorData;
20 | private Throwable cause = null;
21 | private String errorCode = "500";
22 | private String errorMsg = "";
23 |
24 | public WebException(String errorCode, String msg) {
25 | super(msg);
26 | this.errorMsg = msg;
27 | this.errorCode = errorCode;
28 | }
29 |
30 | public WebException(String msg) {
31 | super(msg);
32 | this.errorMsg = msg;
33 | }
34 |
35 |
36 | public WebException(Throwable cause) {
37 | super(cause);
38 | }
39 |
40 | public WebException(String errorCode, String msg, Throwable cause) {
41 | super(msg);
42 | this.cause = cause;
43 | this.errorCode = errorCode;
44 | }
45 |
46 | public WebException(String errorCode, String msg, Object data) {
47 | super(msg);
48 | this.errorData = data;
49 | this.errorCode = errorCode;
50 | }
51 |
52 | @Override
53 | public Throwable getCause() {
54 | return this.cause;
55 | }
56 |
57 | public String getExceptionMessage() {
58 | if (super.getMessage() != null) {
59 | return super.getMessage();
60 | }
61 | if (this.cause != null) {
62 | return this.cause.toString();
63 | }
64 | return null;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/WebThreadLocalManager.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common;
2 |
3 |
4 | public class WebThreadLocalManager {
5 |
6 | private static ThreadLocal currentDataThreadLocal = new ThreadLocal<>();
7 |
8 | public static WebCurrentData get() {
9 | WebCurrentData currentData = currentDataThreadLocal.get();
10 | if (currentData == null) {
11 | currentDataThreadLocal.set(WebCurrentData.builder().build());
12 | }
13 | return currentDataThreadLocal.get();
14 | }
15 |
16 | public static void set(WebCurrentData currentData) {
17 | currentDataThreadLocal.set(currentData);
18 | }
19 |
20 | public static void remove() {
21 | currentDataThreadLocal.remove();
22 | }
23 |
24 | private WebThreadLocalManager() {
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/annotation/FieldAuth.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.annotation;
2 |
3 | import java.lang.annotation.*;
4 |
5 | @Target({ ElementType.METHOD, ElementType.TYPE })
6 | @Retention(RetentionPolicy.RUNTIME)
7 | @Documented
8 | public @interface FieldAuth {
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/annotation/NoAuth.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.annotation;
2 |
3 | import java.lang.annotation.*;
4 |
5 | /**
6 | * 免权限校验
7 | */
8 |
9 | @Target({ ElementType.METHOD, ElementType.TYPE })
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface NoAuth {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/annotation/NoIp.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.annotation;
2 |
3 | import java.lang.annotation.*;
4 |
5 | /**
6 | * 免IP校验
7 | */
8 |
9 | @Target({ ElementType.METHOD, ElementType.TYPE })
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface NoIp {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/annotation/NoLogin.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.annotation;
2 |
3 | import java.lang.annotation.*;
4 |
5 | /**
6 | * 免登录校验
7 | */
8 |
9 | @Target({ ElementType.METHOD, ElementType.TYPE })
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface NoLogin {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/config/SpringFoxConfig.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import springfox.documentation.builders.PathSelectors;
6 | import springfox.documentation.builders.RequestHandlerSelectors;
7 | import springfox.documentation.spi.DocumentationType;
8 | import springfox.documentation.spring.web.plugins.Docket;
9 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
10 |
11 | @Configuration
12 | @EnableSwagger2
13 | public class SpringFoxConfig {
14 | @Bean
15 | public Docket api() {
16 | return new Docket(DocumentationType.SWAGGER_2)
17 | .select()
18 | .apis(RequestHandlerSelectors.any())
19 | .paths(PathSelectors.any())
20 | .build();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/config/WebMvcConfig.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.config;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.AuthInterceptor;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.core.Ordered;
8 | import org.springframework.core.annotation.Order;
9 | import org.springframework.web.cors.CorsConfiguration;
10 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
11 | import org.springframework.web.filter.CorsFilter;
12 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
13 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
14 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | @Configuration
20 | @Order(Ordered.HIGHEST_PRECEDENCE)
21 | public class WebMvcConfig implements WebMvcConfigurer {
22 |
23 |
24 | @Autowired
25 | private AuthInterceptor authInterceptor;
26 |
27 | @Override
28 | public void addInterceptors(InterceptorRegistry registry) {
29 | registry.addInterceptor(authInterceptor).excludePathPatterns("/clash/**","/swagger-resources/**", "/*/api-docs/**", "/images/**", "/lib/**", "/h-ui/**", "/h-ui.admin/**", "/**/favicon.ico")
30 | .excludePathPatterns("/**/*.woff2", "/**/*.css", "/**/*.html", "/**/*.js", "/**/*.png", "/**/*.gif", "/**/*.jpg", "/**/*.jpeg", "/h2/**", "/login", "/error");
31 | }
32 |
33 | @Override
34 | public void addCorsMappings(CorsRegistry registry) {
35 | registry.addMapping("/**")
36 | .allowedOrigins("*")
37 | .allowCredentials(true)
38 | .allowedHeaders("*")
39 | .allowedMethods("GET", "POST", "DELETE", "PUT")
40 | .maxAge(3600);
41 | }
42 |
43 | private CorsConfiguration buildConfig() {
44 | CorsConfiguration corsConfiguration = new CorsConfiguration();
45 | List list = new ArrayList<>();
46 | list.add("*");
47 | corsConfiguration.setAllowedOrigins(list);
48 | corsConfiguration.addAllowedOrigin("*");
49 | corsConfiguration.addAllowedHeader("*");
50 | corsConfiguration.addAllowedMethod("*");
51 | corsConfiguration.setAllowCredentials(true);
52 | return corsConfiguration;
53 | }
54 |
55 | @Bean
56 | public CorsFilter corsFilter() {
57 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
58 | source.registerCorsConfiguration("/**", buildConfig());
59 | return new CorsFilter(source);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/enums/ForwardStatusEnum.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.enums;
2 |
3 | /**
4 | * @program: forwordpanel
5 | * @description: 服务器状态
6 | * @author: liruifeng
7 | * @created: 2020/10/13 16:55
8 | */
9 | public enum ForwardStatusEnum {
10 | INIT(1, "未设置"), STOP(2, "停止中"), START(3, "启动中"),
11 | STOPPED(4, "已停止"), STARTED(5, "已启动"),STOP_FAIL(6, "停止失败"),START_FAIL(7, "启动失败");
12 |
13 | ForwardStatusEnum(int code, String name) {
14 | this.code = code;
15 | this.name = name;
16 | }
17 |
18 | private int code;
19 | private String name;
20 |
21 | public int getCode() {
22 | return code;
23 | }
24 |
25 | public String getName() {
26 | return name;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/enums/ServerStatusEnum.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.enums;
2 |
3 | /**
4 | * @program: forwordpanel
5 | * @description: 服务器状态
6 | * @author: liruifeng
7 | * @created: 2020/10/13 16:55
8 | */
9 | public enum ServerStatusEnum {
10 | INIT(1, "初始化中"), CONNECT_FAIL(2, "连接失败"), ONLINE(3, "在线");
11 |
12 | ServerStatusEnum(int code, String name) {
13 | this.code = code;
14 | this.name = name;
15 | }
16 |
17 | private int code;
18 | private String name;
19 |
20 | public int getCode() {
21 | return code;
22 | }
23 |
24 | public String getName() {
25 | return name;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/response/ApiResponse.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.response;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.IStatusMessage;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | /**
9 | * @Author: meishaoyong
10 | * @Date: 2019/11/8 13:41
11 | * @Description:
12 | */
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class ApiResponse {
17 |
18 | private String code = "0";
19 |
20 | private String msg = "";
21 |
22 | private T data;
23 |
24 | private Boolean success;
25 |
26 | public static ApiResponse ok() {
27 | ApiResponse apiResponse = new ApiResponse();
28 | apiResponse.setSuccess(true);
29 | return apiResponse;
30 | }
31 |
32 | public static ApiResponse ok(T data) {
33 | ApiResponse result = ok();
34 | result.setData(data);
35 | return result;
36 | }
37 |
38 | public static ApiResponse ok(String code, String msg, T data) {
39 | ApiResponse result = ok();
40 | result.setCode(code);
41 | result.setMsg(msg);
42 | result.setData(data);
43 | return result;
44 | }
45 |
46 | public static ApiResponse ok(IStatusMessage.SystemStatus systemStatus) {
47 | ApiResponse result = new ApiResponse();
48 | result.setCode(systemStatus.getCode());
49 | result.setMsg(systemStatus.getMessage());
50 | result.setSuccess(true);
51 | return result;
52 | }
53 |
54 | public static ApiResponse error(String code, String msg) {
55 | ApiResponse result = new ApiResponse();
56 | result.setCode(code);
57 | result.setMsg(msg);
58 | result.setSuccess(false);
59 | return result;
60 | }
61 |
62 | public static ApiResponse error(IStatusMessage.SystemStatus systemStatus) {
63 | ApiResponse result = new ApiResponse();
64 | result.setCode(systemStatus.getCode());
65 | result.setMsg(systemStatus.getMessage());
66 | result.setSuccess(false);
67 | return result;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/response/PageDataResult.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.response;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @Title: PageDataResult
7 | * @Description: 封装DTO分页数据(记录数和所有记录)
8 | * @author: youqing
9 | * @version: 1.0
10 | * @date: 2018/11/21 11:15
11 | */
12 | public class PageDataResult {
13 |
14 | private Integer code=200;
15 |
16 | //总记录数量
17 | private Long total;
18 |
19 | private List> list;
20 |
21 | public Integer getCode() {
22 | return code;
23 | }
24 |
25 | public void setCode(Integer code) {
26 | this.code = code;
27 | }
28 |
29 | public Long getTotal() {
30 | return total;
31 | }
32 |
33 | public void setTotal(Long total) {
34 | this.total = total;
35 | }
36 |
37 | public List > getList() {
38 | return list;
39 | }
40 |
41 | public void setList(List > list) {
42 | this.list = list;
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "PageDataResult{" +
48 | "code=" + code +
49 | ", totals=" + total +
50 | ", list=" + list +
51 | '}';
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/response/ResponseResult.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.response;
2 |
3 |
4 | import com.leeroy.forwordpanel.forwordpanel.common.IStatusMessage;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @Title: ResponseResult
10 | * @Description: 前端请求响应结果,code:编码,message:描述,obj对象,可以是单个数据对象,数据列表或者PageInfo
11 | * @author: youqing
12 | * @version: 1.0
13 | * @date: 2018/11/23 9:48
14 | */
15 | public class ResponseResult implements Serializable{
16 |
17 | private String code;
18 | private String message;
19 | private Object obj;
20 |
21 | public ResponseResult() {
22 | this.code = IStatusMessage.SystemStatus.SUCCESS.getCode();
23 | this.message = IStatusMessage.SystemStatus.SUCCESS.getMessage();
24 | }
25 |
26 | public ResponseResult(IStatusMessage statusMessage){
27 | this.code = statusMessage.getCode();
28 | this.message = statusMessage.getMessage();
29 |
30 | }
31 |
32 | public String getCode() {
33 | return code;
34 | }
35 |
36 | public void setCode(String code) {
37 | this.code = code;
38 | }
39 |
40 | public String getMessage() {
41 | return message;
42 | }
43 |
44 | public void setMessage(String message) {
45 | this.message = message;
46 | }
47 |
48 | public Object getObj() {
49 | return obj;
50 | }
51 |
52 | public void setObj(Object obj) {
53 | this.obj = obj;
54 | }
55 |
56 | @Override public String toString() {
57 | return "ResponseResult{" + "code='" + code + '\'' + ", message='"
58 | + message + '\'' + ", obj=" + obj + '}';
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/BeanCopyUtil.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import org.springframework.beans.BeanUtils;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.function.Supplier;
8 |
9 | public class BeanCopyUtil extends BeanUtils {
10 |
11 | /**
12 | * 集合数据的拷贝
13 | * @param sources: 数据源类
14 | * @param target: 目标类::new(eg: UserVO::new)
15 | * @return
16 | */
17 | public static List copyListProperties(List sources, Supplier target) {
18 | return copyListProperties(sources, target, null);
19 | }
20 |
21 |
22 | /**
23 | * 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
24 | * @param sources: 数据源类
25 | * @param target: 目标类::new(eg: UserVO::new)
26 | * @param callBack: 回调函数
27 | * @return
28 | */
29 | public static List copyListProperties(List sources, Supplier target, BeanCopyUtilCallBack callBack) {
30 | List list = new ArrayList<>(sources.size());
31 | for (S source : sources) {
32 | T t = target.get();
33 | copyProperties(source, t);
34 | list.add(t);
35 | if (callBack != null) {
36 | // 回调
37 | callBack.callBack(source, t);
38 | }
39 | }
40 | return list;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/BeanCopyUtilCallBack.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | @FunctionalInterface
4 | public interface BeanCopyUtilCallBack {
5 |
6 | /**
7 | * 定义默认回调方法
8 | * @param t
9 | * @param s
10 | */
11 | void callBack(S t, T s);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/CertUtil.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 |
4 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoAuth;
5 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoIp;
6 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoLogin;
7 | import org.springframework.web.method.HandlerMethod;
8 |
9 | public class CertUtil {
10 |
11 | public static boolean checkNoLogin(Object handler){
12 | if (!(handler instanceof HandlerMethod)) {
13 | return true;
14 | }
15 | boolean result=false;
16 | HandlerMethod handlerMethod = (HandlerMethod) handler;
17 | //String methodName = handlerMethod.getMethod().getName();
18 | // 判断是否需要检查登录(方法)
19 | NoLogin noLogin = handlerMethod.getMethod().getAnnotation(NoLogin.class);
20 | if (null != noLogin) {
21 | result= true;
22 | }
23 | // 判断是否需要检查登录(类)
24 | noLogin = handlerMethod.getMethod().getDeclaringClass().getAnnotation(NoLogin.class);
25 | if (null != noLogin) {
26 | result= true;
27 | }
28 | return result;
29 | }
30 |
31 | public static boolean checkNoAuth(Object handler){
32 | if (!(handler instanceof HandlerMethod)) {
33 | return true;
34 | }
35 | boolean result=false;
36 | HandlerMethod handlerMethod = (HandlerMethod) handler;
37 | //String methodName = handlerMethod.getMethod().getName();
38 | // 判断是否需要检查权限(方法)
39 | NoAuth noAuth = handlerMethod.getMethod().getAnnotation(NoAuth.class);
40 | if (null != noAuth) {
41 | result= true;
42 | }
43 | // 判断是否需要检查权限(类)
44 | noAuth = handlerMethod.getMethod().getDeclaringClass().getAnnotation(NoAuth.class);
45 | if (null != noAuth) {
46 | result= true;
47 | }
48 | return result;
49 | }
50 |
51 | public static boolean checkNoIp(Object handler){
52 | if (!(handler instanceof HandlerMethod)) {
53 | return true;
54 | }
55 | boolean result=false;
56 | HandlerMethod handlerMethod = (HandlerMethod) handler;
57 | String methodName = handlerMethod.getMethod().getName();
58 | // 判断是否需要检查IP(方法)
59 | NoIp noIp = handlerMethod.getMethod().getAnnotation(NoIp.class);
60 | if (null != noIp) {
61 | result= true;
62 | }
63 | // 判断是否需要检查IP(类)
64 | noIp = handlerMethod.getMethod().getDeclaringClass().getAnnotation(NoIp.class);
65 | if (null != noIp) {
66 | result= true;
67 | }
68 | return result;
69 | }
70 |
71 | public static boolean checkIpInRange(String ip, String cidr) {
72 | boolean result=false;
73 | if(cidr.contains("/")){
74 | String[] ips = ip.split("\\.");
75 | int ipAddr = (Integer.parseInt(ips[0]) << 24)
76 | | (Integer.parseInt(ips[1]) << 16)
77 | | (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]);
78 | int type = Integer.parseInt(cidr.replaceAll(".*/", ""));
79 | int mask = 0xFFFFFFFF << (32 - type);
80 | String cidrIp = cidr.replaceAll("/.*", "");
81 | String[] cidrIps = cidrIp.split("\\.");
82 | int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24)
83 | | (Integer.parseInt(cidrIps[1]) << 16)
84 | | (Integer.parseInt(cidrIps[2]) << 8)
85 | | Integer.parseInt(cidrIps[3]);
86 |
87 | result= (ipAddr & mask) == (cidrIpAddr & mask);
88 | }else{
89 | result=ip.equals(cidr);
90 | }
91 | return result;
92 |
93 | }
94 | public static void main(String[] args) {
95 | System.out.println(checkIpInRange("192.168.1.128", "192.168.1.64/26"));
96 | System.out.println(checkIpInRange("192.168.1.2", "192.168.0.0/23"));
97 | System.out.println(checkIpInRange("192.168.0.1", "192.168.0.0/24"));
98 | System.out.println(checkIpInRange("192.168.0.0", "192.168.0.0/32"));
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/DateUtils.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import java.text.DateFormat;
4 | import java.text.ParseException;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Calendar;
7 | import java.util.Date;
8 |
9 | /**
10 | * @Title: DateUtils
11 | * @Description:
12 | * @author: youqing
13 | * @version: 1.0
14 | * @date: 2018/5/26 9:58
15 | */
16 | public class DateUtils {
17 |
18 | /**
19 | *
20 | * 功能描述:
21 | *
22 | * @param: 获取当前系统时间 yyyy-MM-dd HH:mm:ss
23 | * @return:
24 | * @auther: youqing
25 | * @date: 2018/5/26 9:59
26 | */
27 | public static String getCurrentDate(){
28 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
29 | String date = df.format(System.currentTimeMillis());
30 | return date;
31 | }
32 |
33 |
34 | /**
35 | *
36 | * 功能描述:
37 | *
38 | * @param: date类 获取当前系统时间 yyyy-MM-dd HH:mm:ss
39 | * @return:
40 | * @auther: youqing
41 | * @date: 2018/5/26 10:39
42 | */
43 | public static Date getCurrentDateToDate () {
44 | DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
45 | String date = df.format(System.currentTimeMillis());
46 | Date d = null;
47 | try {
48 | d = df.parse( date.toString( ) );
49 | } catch ( ParseException e ) {
50 | e.printStackTrace( );
51 | }
52 | return d;
53 | }
54 |
55 | /**
56 | * 增加时间单位:天
57 | * @param day
58 | * @return
59 | */
60 | public static String getCurrentAddDay(int day) {
61 | SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
62 | Calendar cal = Calendar.getInstance();
63 | cal.setTime(new Date());
64 | cal.add(Calendar.DATE, day);
65 | return sdf.format(cal.getTime());
66 | }
67 |
68 | /**
69 | * 增加时间单位:分钟
70 | * @param minute
71 | * @return
72 | */
73 | public static String getCurrentAddMin(int minute) {
74 | SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
75 | Calendar cal = Calendar.getInstance();
76 | cal.setTime(new Date());
77 | cal.add(Calendar.MINUTE, minute);
78 | return sdf.format(cal.getTime());
79 | }
80 |
81 | /**
82 | * 获取当前时间
83 | * @return
84 | */
85 | public static String getNowDateString ( ) {
86 | Date d = new Date();
87 | SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
88 | return sdf.format( d );
89 | }
90 |
91 | /**
92 | * 把Date转为String
93 | * @param date
94 | * @param format
95 | * @return
96 | */
97 | public static String getFormatTime(Date date, String format) {
98 | SimpleDateFormat sdf = new SimpleDateFormat(format);
99 | return sdf.format(date);
100 | }
101 |
102 | /**
103 | * 增加时间单位:天
104 | * @param day
105 | * @return
106 | */
107 | public static Date addDay(int day) {
108 | Calendar cal = Calendar.getInstance();
109 | cal.setTime(new Date());
110 | cal.add(Calendar.DATE, day);
111 | return cal.getTime();
112 | }
113 |
114 | /**
115 | * 增加时间单位:天
116 | * @param date
117 | * @param day
118 | * @return
119 | */
120 | public static Date addDay(Date date, int day) {
121 | Calendar cal = Calendar.getInstance();
122 | cal.setTime(date);
123 | cal.add(Calendar.DATE, day);
124 | return cal.getTime();
125 | }
126 |
127 | /**
128 | * 减去多少天
129 | * @param date
130 | * @param day
131 | * @return
132 | */
133 | public static Date minusDay(Date date, int day) {
134 | return addDay(date, -day);
135 | }
136 |
137 | public static void main(String[] args) {
138 | System.out.println(getCurrentAddDay(2));
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/DigestUtils.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | /**
4 | * @Title: DigestUtils
5 | * @Description:
6 | * @author: youqing
7 | * @version: 1.0
8 | * @date: 2018/9/11 15:09
9 | */
10 | public class DigestUtils {
11 |
12 | /**
13 | *
14 | * 功能描述: MD5加密账号密码
15 | *
16 | * @param:
17 | * @return:
18 | * @auther: youqing
19 | * @date: 2018/9/11 15:11
20 | */
21 | public static String Md5(String userName,String password){
22 | return org.apache.commons.codec.digest.DigestUtils.md5Hex(userName+password);
23 | }
24 |
25 |
26 | public static String Md5(String userName,String password, Long time){
27 | return org.apache.commons.codec.digest.DigestUtils.md5Hex(userName+password+time);
28 | }
29 |
30 | public static void main(String[] args) {
31 | System.out.println(org.apache.commons.codec.digest.DigestUtils.md5Hex("admin"+"123456"));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/IpUtil.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import java.net.*;
4 | import java.util.Enumeration;
5 |
6 | public class IpUtil {
7 | public static final String DEFAULT_IP = "127.0.0.1";
8 |
9 | /**
10 | * 直接根据第一个网卡地址作为其内网ipv4地址,避免返回 127.0.0.1
11 | *
12 | * @return
13 | */
14 | public static String getLocalIpByNetcard() {
15 | try {
16 | for (Enumeration e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {
17 | NetworkInterface item = e.nextElement();
18 | for (InterfaceAddress address : item.getInterfaceAddresses()) {
19 | if (item.isLoopback() || !item.isUp()) {
20 | continue;
21 | }
22 | if (address.getAddress() instanceof Inet4Address) {
23 | Inet4Address inet4Address = (Inet4Address) address.getAddress();
24 | return inet4Address.getHostAddress();
25 | }
26 | }
27 | }
28 | return InetAddress.getLocalHost().getHostAddress();
29 | } catch (SocketException | UnknownHostException e) {
30 | throw new RuntimeException(e);
31 | }
32 | }
33 |
34 | public static String getLocalIP() {
35 | try {
36 | return InetAddress.getLocalHost().getHostAddress();
37 | } catch (UnknownHostException e) {
38 | throw new RuntimeException(e);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/ShellUtil.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.InputStreamReader;
7 |
8 | @Slf4j
9 | public class ShellUtil {
10 |
11 | public static String execShell(String shell) {
12 |
13 | log.info("execute shell: {}", shell);
14 | try {
15 | if(isWindows()){
16 | return "";
17 | }
18 | String[] cmd = new String[]{"/bin/sh", "-c", shell};
19 | Process ps = Runtime.getRuntime().exec(cmd);
20 | ps.waitFor();
21 | BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
22 | StringBuffer sb = new StringBuffer();
23 | String line;
24 | while ((line = br.readLine()) != null) {
25 | sb.append(line).append("\n");
26 | }
27 | String result = sb.toString();
28 | log.info("shell result: {}", result);
29 | return sb.toString();
30 | } catch (Exception e) {
31 | log.error("----error-----");
32 | e.printStackTrace();
33 | }
34 | return null;
35 | }
36 |
37 | public static boolean isWindows() {
38 | return System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/SimpleForward.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.OutputStream;
8 | import java.net.ServerSocket;
9 | import java.net.Socket;
10 | import java.util.*;
11 |
12 | @Slf4j
13 | public class SimpleForward extends Thread {
14 | // 服务器
15 | private ServerSocket server;
16 | // 监听本地端口
17 | private int localPort = 1080;
18 | // 目标主机地址
19 | private String remoteHostAddr = "0.0.0.0";
20 | // 目标主机端口
21 | private int remoteHostPort = 8388;
22 | // 设置超时时间 30s
23 | private static int TIMEOUT = 30;
24 | // 结束标志
25 | volatile boolean runFlag = true;
26 | // 客户端列表 用于删除失效连接和超时连接
27 | private static HashMap clientList = new HashMap<>();
28 |
29 | public static void main(String[] args) {
30 | new SimpleForward(1234, "143.92.44.202", 443);
31 | }
32 |
33 |
34 | public SimpleForward(int localPort, String remoteHostAddr, int remoteHostPort) {
35 | this.localPort = localPort;
36 | this.remoteHostAddr = remoteHostAddr;
37 | this.remoteHostPort = remoteHostPort;
38 | }
39 |
40 | public void stopForward(){
41 | try {
42 | server.close();
43 | } catch (IOException e) {
44 | log.error("close error", e);
45 | }
46 | this.runFlag = false;
47 | }
48 |
49 | @Override
50 | public void run() {
51 | try {
52 | this.server = new ServerSocket(this.localPort);
53 | log.info("服务器开启成功");
54 | log.info("监听端口 : " + this.localPort);
55 | } catch (IOException e) {
56 | log.info("服务器开启失败");
57 | log.info(e.getMessage());
58 | log.info("退出运行");
59 | return;
60 | }
61 | new Thread(new AutoDestroy()).start();
62 | while (runFlag) {
63 | Socket socket = null;
64 | Socket remoteHost = null;
65 | try {
66 | socket = server.accept();
67 | // 接收到请求就把socket扔进map,value为刷新时间
68 | clientList.put(socket, new Date());
69 | String address = socket.getRemoteSocketAddress().toString();
70 | log.debug("新连接 : " + address);
71 | // 建立与目标主机的连接
72 | remoteHost = new Socket(this.remoteHostAddr, this.remoteHostPort);
73 | log.debug("连接地址 : " + this.remoteHostAddr + ":" + this.remoteHostPort);
74 | // 端口转发
75 | new Thread(new Switch(socket, remoteHost, remoteHost.getInputStream(), socket.getOutputStream())).start();
76 | new Thread(new Switch(socket, remoteHost, socket.getInputStream(), remoteHost.getOutputStream())).start();
77 | } catch (IOException e) {
78 | log.info("连接异常");
79 | log.info(e.getMessage());
80 | close(socket);
81 | close(remoteHost);
82 | }
83 | }
84 | log.info("closed...");
85 | }
86 |
87 | private void close(Socket socket) {
88 | try {
89 | if (socket != null) {
90 | socket.close();
91 | }
92 | } catch (IOException e) {
93 | e.printStackTrace();
94 | }
95 | }
96 |
97 | // 用于端口转发
98 | private class Switch implements Runnable {
99 | private Socket host;
100 | private Socket remoteHost;
101 | private InputStream in;
102 | private OutputStream out;
103 |
104 | Switch(Socket host, Socket remoteHost, InputStream in, OutputStream out) {
105 | this.host = host;
106 | this.remoteHost = remoteHost;
107 | this.in = in;
108 | this.out = out;
109 | }
110 |
111 | @Override
112 | public void run() {
113 | int length;
114 | byte[] buffer = new byte[1024];
115 | try {
116 | while (!host.isClosed() && (length = in.read(buffer)) > -1) {
117 | clientList.put(host, new Date());
118 | out.write(buffer, 0, length);
119 | }
120 | } catch (IOException e) {
121 | log.debug("连接关闭");
122 | } finally {
123 | close(host);
124 | close(remoteHost);
125 | }
126 | }
127 | }
128 |
129 | // 用于清除失效连接和超时连接
130 | private class AutoDestroy implements Runnable {
131 | @Override
132 | public void run() {
133 | Timer timer = new Timer();
134 | timer.schedule(new TimerTask() {
135 | @Override
136 | public void run() {
137 | List list = new LinkedList<>();
138 | log.info("开始扫描失效与超时连接");
139 | Date start = new Date();
140 | for (Socket socket : clientList.keySet()) {
141 | Date lastTime = clientList.get(socket);
142 | long time = new Date().getTime() - lastTime.getTime();
143 | if (socket.isClosed() || time / 1000 >= TIMEOUT) {
144 | list.add(socket);
145 | }
146 | }
147 | log.info("找到" + list.size() + "个,用时 : " + (new Date().getTime() - start.getTime()) + "毫秒");
148 | log.info("开始清除失效与超时连接");
149 | for (Socket socket : list) {
150 | try {
151 | clientList.remove(socket);
152 | socket.close();
153 | } catch (IOException e) {
154 | e.printStackTrace();
155 | }
156 | }
157 | log.info("当前连接数 : " + clientList.size());
158 | }
159 | }, 30 * 1000, 30 * 1000);
160 | }
161 | }
162 |
163 | // private class Terminal implements Runnable {
164 | // private String format = "yyyy-MM-dd HH:mm:ss";
165 | // private SimpleDateFormat dateFormat = new SimpleDateFormat(format);
166 | //
167 | // @Override
168 | // public void run() {
169 | // while (!server.isClosed()) {
170 | // System.out.print("请输入命令 : ");
171 | // String cmd = reader.readKB();
172 | // handler(cmd);
173 | // }
174 | // }
175 | //
176 | // private void handler(String cmd) {
177 | // switch (cmd) {
178 | // case "status":
179 | // log.info("当前时间 : " + dateFormat.format(new Date()));
180 | // log.info("总连接数 : " + clientList.size());
181 | // for (Socket socket : clientList.keySet()) {
182 | // long time = new Date().getTime() - clientList.get(socket).getTime();
183 | // log.info("<" + socket.getRemoteSocketAddress().toString() + "> " + time / 1000);
184 | // }
185 | // break;
186 | // }
187 | // }
188 | // }
189 | }
190 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/TokenUtil.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 |
8 | @Slf4j
9 | public class TokenUtil {
10 |
11 | private TokenUtil() {
12 | }
13 |
14 | private static final String TOKEN_KEY = "123456abc";
15 |
16 | /**
17 | * @param userName 用户名
18 | * @param password 密码
19 | * @return
20 | */
21 | public static String makeToken(String userName, String password) {
22 | Long now = System.currentTimeMillis();
23 | return DigestUtils.Md5(userName, password, now);
24 | }
25 |
26 |
27 | /**
28 | * get token from request
29 | *
30 | * @param request
31 | * @return
32 | */
33 | public static String getToken(HttpServletRequest request) {
34 | return request.getHeader("X-Token");
35 | }
36 |
37 | private static String getTokenFromCookies(HttpServletRequest request) {
38 | Cookie[] cookies = request.getCookies();
39 | if(cookies==null||cookies.length==0){
40 | return null;
41 | }
42 | for (Cookie cookie : cookies) {
43 | if ("token".equals(cookie.getName())) {
44 | return cookie.getValue();
45 | }
46 | }
47 | return null;
48 | }
49 |
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/remotessh/KeyLoginUserInfo.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util.remotessh;
2 |
3 | import com.jcraft.jsch.UIKeyboardInteractive;
4 | import com.jcraft.jsch.UserInfo;
5 |
6 | public class KeyLoginUserInfo implements UserInfo, UIKeyboardInteractive {
7 |
8 | @Override
9 |
10 | public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
11 | return null;
12 | }
13 |
14 | @Override
15 | public String getPassphrase() {
16 | return null;
17 | }
18 |
19 |
20 | @Override
21 |
22 | public String getPassword() {
23 |
24 |
25 | return null;
26 |
27 | }
28 |
29 |
30 | @Override
31 |
32 | public boolean promptPassword(String message) {
33 |
34 | // TODO Auto-generated method stub
35 |
36 | return true;
37 |
38 | }
39 |
40 |
41 | @Override
42 |
43 | public boolean promptPassphrase(String message) {
44 |
45 | // TODO Auto-generated method stub
46 |
47 | return true;
48 |
49 | }
50 |
51 |
52 | @Override
53 |
54 | public boolean promptYesNo(String message) {
55 | return true;
56 | }
57 |
58 |
59 | @Override
60 |
61 | public void showMessage(String message) {
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/remotessh/MyUserInfo.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util.remotessh;
2 |
3 | import com.jcraft.jsch.UserInfo;
4 |
5 | /**
6 | * This class provide interface to feedback information to the user.
7 | */
8 | public class MyUserInfo implements UserInfo {
9 | private String password;
10 |
11 | private String passphrase;
12 |
13 | @Override
14 | public String getPassphrase() {
15 | System.out.println("MyUserInfo.getPassphrase()");
16 | return null;
17 | }
18 |
19 | @Override
20 | public String getPassword() {
21 | System.out.println("MyUserInfo.getPassword()");
22 | return null;
23 | }
24 |
25 | @Override
26 | public boolean promptPassphrase(final String arg0) {
27 | System.out.println("MyUserInfo.promptPassphrase()");
28 | System.out.println(arg0);
29 | return false;
30 | }
31 |
32 | @Override
33 | public boolean promptPassword(final String arg0) {
34 | System.out.println("MyUserInfo.promptPassword()");
35 | System.out.println(arg0);
36 | return false;
37 | }
38 |
39 | @Override
40 | public boolean promptYesNo(final String arg0) {
41 | System.out.println("MyUserInfo.promptYesNo()");
42 | System.out.println(arg0);
43 | if (arg0.contains("The authenticity of host")) {
44 | return true;
45 | }
46 | return false;
47 | }
48 |
49 | @Override
50 | public void showMessage(final String arg0) {
51 | System.out.println("MyUserInfo.showMessage()");
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/common/util/remotessh/SSHCommandExecutor.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.common.util.remotessh;
2 |
3 | import com.jcraft.jsch.*;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.apache.commons.lang3.ClassPathUtils;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.springframework.core.io.ClassPathResource;
9 | import org.springframework.util.CollectionUtils;
10 | import org.springframework.util.ResourceUtils;
11 | import org.springframework.web.servlet.resource.PathResourceResolver;
12 |
13 | import java.io.*;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.Properties;
17 | import java.util.Vector;
18 |
19 | /**
20 | * This class provide interface to execute command on remote Linux.
21 | */
22 | @Slf4j
23 | public class SSHCommandExecutor {
24 | private String ipAddress;
25 |
26 | private String username;
27 |
28 | private String password;
29 |
30 | private String privateKeyPath;
31 |
32 | public int port = 34204;
33 |
34 | private Vector stdout;
35 |
36 | public String getIpAddress() {
37 | return ipAddress;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public SSHCommandExecutor(final String ipAddress, final String username, final String password) {
45 | this.ipAddress = ipAddress;
46 | this.username = username;
47 | this.password = password;
48 | stdout = new Vector<>();
49 | }
50 |
51 | public SSHCommandExecutor(Server server) {
52 | this.ipAddress = server.getHost();
53 | this.port = server.getPort();
54 | this.username = server.getUsername();
55 | // this.privateKeyPath = server.getPassword();
56 | this.password = server.getPassword();
57 | stdout = new Vector<>();
58 | }
59 |
60 |
61 | public SSHCommandExecutor(Server server, final String username, final String privateKeyPath) {
62 | this.ipAddress = server.getHost();
63 | this.port = server.getPort();
64 | this.username = username;
65 | this.privateKeyPath = privateKeyPath;
66 | stdout = new Vector<>();
67 | }
68 |
69 | public int execute(final String... commandList) {
70 | stdout.clear();
71 | int returnCode = 0;
72 | JSch jsch = new JSch();
73 | MyUserInfo userInfo = new MyUserInfo();
74 | try {
75 | Session session = jsch.getSession(username, ipAddress, port);
76 | session.setPassword(password);
77 | session.setUserInfo(userInfo);
78 | session.connect();
79 | for (String command : commandList) {
80 | // Create and connect channel.
81 | Channel channel = session.openChannel("exec");
82 | ((ChannelExec) channel).setCommand(command);
83 | channel.setInputStream(null);
84 | BufferedReader input = new BufferedReader(new InputStreamReader(channel
85 | .getInputStream()));
86 | channel.connect();
87 | log.info("The remote command is: {}", command);
88 |
89 | // Get the output of remote command.
90 | String line;
91 | while ((line = input.readLine()) != null) {
92 | stdout.add(line);
93 | }
94 | input.close();
95 | // Get the return code only after the channel is closed.
96 | if (channel.isClosed()) {
97 | returnCode = channel.getExitStatus();
98 | }
99 | // Disconnect the channel and session.
100 | channel.disconnect();
101 | }
102 |
103 | session.disconnect();
104 | } catch (Exception e) {
105 | log.error("执行shell失败", e);
106 | }
107 | log.info("shell result: {}", StringUtils.join(stdout));
108 | return returnCode;
109 | }
110 |
111 | /**
112 | * 执行脚本
113 | * @param script
114 | * @return
115 | */
116 | public void executeScript(final String script) {
117 | try {
118 | List commandList = new ArrayList<>();
119 | ClassPathResource resource = new ClassPathResource("scripts/" + script);
120 | BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
121 | String str;
122 | while ((str = br.readLine()) != null) {
123 | commandList.add(str);
124 | }
125 | execute(commandList.toArray(new String[]{}));
126 | } catch (Exception e) {
127 | e.printStackTrace();
128 | }
129 | }
130 |
131 | public Vector getResultSet() {
132 | return stdout;
133 | }
134 |
135 | public String getResult() {
136 | return CollectionUtils.isEmpty(stdout) ? "" : stdout.get(0);
137 | }
138 |
139 | public static void main(final String[] args) {
140 | SSHCommandExecutor sshExecutor = new SSHCommandExecutor("120.241.154.4", "root", "28L8CegNk9");
141 | long stsart = System.currentTimeMillis();
142 | sshExecutor.execute("netstat -tunlp", "netstat -tunlp", "netstat -tunlp", "netstat -tunlp");
143 | Vector stdout = sshExecutor.getResultSet();
144 | for (String str : stdout) {
145 | System.out.println(str);
146 | }
147 | System.out.println(System.currentTimeMillis() - stsart);
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/ConfigController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoLogin;
5 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
7 | import com.leeroy.forwordpanel.forwordpanel.model.Clash;
8 | import com.leeroy.forwordpanel.forwordpanel.service.ConfigService;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.web.bind.annotation.*;
12 |
13 | import javax.servlet.http.HttpServletResponse;
14 | import java.io.IOException;
15 | import java.io.OutputStream;
16 |
17 | @RequestMapping("config")
18 | @Controller
19 | public class ConfigController {
20 |
21 | @Autowired
22 | private ConfigService configService;
23 |
24 |
25 | @ResponseBody
26 | @PostMapping("getPage")
27 | public ApiResponse getPage(@RequestBody PageRequest pageRequest) {
28 | return ApiResponse.ok(configService.findClashList(pageRequest));
29 | }
30 |
31 | @ResponseBody
32 | @PostMapping("save")
33 | public ApiResponse save(@RequestBody Clash clash) {
34 | return configService.save(clash);
35 | }
36 |
37 | @ResponseBody
38 | @GetMapping("delete")
39 | public ApiResponse delete(String id) {
40 | configService.delClash(id);
41 | return ApiResponse.ok();
42 | }
43 |
44 | @GetMapping("getNodeList")
45 | @ResponseBody
46 | public ApiResponse getNodeList(String id){
47 | return configService.getNodeList(id);
48 | }
49 |
50 | @PostMapping("saveNodeList")
51 | @ResponseBody
52 | public ApiResponse saveNodeList(@RequestBody JSONArray nodeList, @RequestParam String id){
53 | return configService.saveNodeList(nodeList, id);
54 | }
55 |
56 |
57 | @NoLogin
58 | @ResponseBody
59 | @GetMapping("/{id}")
60 | public void getClashFileById(@PathVariable String id, HttpServletResponse response) {
61 | Clash clash = configService.findClashById(id);
62 | try {
63 | String text = clash.getText();
64 | byte[] bytes = text.getBytes("UTF-8");
65 | response.setContentType("application/octet-stream;charset=UTF-8");
66 | response.setHeader("Content-Disposition", "attachment; filename=\"" + id + ".yml\"");
67 | response.addHeader("Content-Length", "" + bytes.length);
68 | OutputStream stream = null;
69 | stream = response.getOutputStream();
70 | stream.write(bytes);
71 | stream.flush();
72 | stream.close();
73 | } catch (IOException e) {
74 | e.printStackTrace();
75 | }
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.ui.Model;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.servlet.ModelAndView;
10 |
11 | /**
12 | * @Title: LoginController
13 | * @Description:
14 | * @author: youqing
15 | * @version: 1.0
16 | * @date: 2018/11/20 11:39
17 | */
18 | @Controller
19 | public class IndexController {
20 |
21 | private Logger logger = LoggerFactory.getLogger(this.getClass());
22 |
23 |
24 | @RequestMapping("login")
25 | public String tologin(){
26 | logger.info("定向登陆页");
27 | return "login";
28 | }
29 |
30 |
31 | @RequestMapping("home")
32 | public String home(Model model){
33 | logger.info("定向主页");
34 | model.addAttribute("username", WebCurrentData.getUserName());
35 | return "home";
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoAuth;
4 | import com.leeroy.forwordpanel.forwordpanel.common.annotation.NoLogin;
5 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
6 | import com.leeroy.forwordpanel.forwordpanel.common.util.TokenUtil;
7 | import com.leeroy.forwordpanel.forwordpanel.dto.LoginDTO;
8 | import com.leeroy.forwordpanel.forwordpanel.service.LoginService;
9 | import com.leeroy.forwordpanel.forwordpanel.service.UserTokenService;
10 | import io.swagger.annotations.Api;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.validation.annotation.Validated;
14 | import org.springframework.web.bind.annotation.*;
15 | import org.springframework.web.servlet.ModelAndView;
16 |
17 | import javax.servlet.http.HttpServletRequest;
18 |
19 | @Slf4j
20 | @Api(value = "登录")
21 | @RestController
22 | @Validated
23 | public class LoginController {
24 |
25 | @Autowired
26 | private LoginService loginService;
27 |
28 | @Autowired
29 | private UserTokenService userTokenService;
30 |
31 | @NoLogin
32 | @NoAuth
33 | @PostMapping("/login")
34 | @ResponseBody
35 | public ApiResponse login(@RequestBody LoginDTO loginDTO) {
36 | return loginService.login(loginDTO);
37 | }
38 |
39 | @NoLogin
40 | @NoAuth
41 | @GetMapping("/authToken")
42 | @ResponseBody
43 | public ApiResponse authToken(String token){
44 | return ApiResponse.ok(userTokenService.getUserByToken(token));
45 | }
46 |
47 | @RequestMapping("/logout")
48 | @NoLogin
49 | public ApiResponse logout(HttpServletRequest request) {
50 | String token = TokenUtil.getToken(request);
51 | userTokenService.delToken(token);
52 | ModelAndView modelAndView = new ModelAndView();
53 | modelAndView.setViewName("login");
54 | return ApiResponse.ok();
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/PortController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.PortAddDTO;
7 | import com.leeroy.forwordpanel.forwordpanel.dto.PortPageRequest;
8 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
9 | import com.leeroy.forwordpanel.forwordpanel.service.PortService;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Controller;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | @RequestMapping("port")
15 | @Controller
16 | public class PortController {
17 |
18 | @Autowired
19 | private PortService portService;
20 |
21 | @ResponseBody
22 | @PostMapping("getPortList")
23 | public ApiResponse getPortList(@RequestBody PortPageRequest pageRequest) {
24 | return ApiResponse.ok(portService.findListByServer(pageRequest));
25 | }
26 |
27 | @ResponseBody
28 | @PostMapping("getPage")
29 | public ApiResponse getUserPortList(@RequestBody PageRequest pageRequest) {
30 | return ApiResponse.ok(portService.findList(pageRequest));
31 | }
32 |
33 | @ResponseBody
34 | @GetMapping("getFreePortList")
35 | public ApiResponse getFreePortList(Integer serverId) {
36 | return ApiResponse.ok(portService.findFreePortList(serverId));
37 | }
38 |
39 | @ResponseBody
40 | @GetMapping("getFreePortPage")
41 | public ApiResponse getFreePortPage(PortPageRequest portPageRequest) {
42 | return ApiResponse.ok(portService.findFreePortPage(portPageRequest));
43 | }
44 |
45 |
46 | @ResponseBody
47 | @RequestMapping(value = "save", method = RequestMethod.POST)
48 | public ApiResponse saveUserPort(@RequestBody Port port) {
49 | if(WebCurrentData.getUser().getUserType()>0){
50 | return ApiResponse.error("403", "您没有权限执行此操作");
51 | }
52 | return portService.save(port);
53 | }
54 |
55 | @ResponseBody
56 | @RequestMapping(value = "batchSave", method = RequestMethod.POST)
57 | public ApiResponse saveUserPort(@RequestBody PortAddDTO port) {
58 | if(WebCurrentData.getUser().getUserType()>0){
59 | return ApiResponse.error("403", "您没有权限执行此操作");
60 | }
61 | return portService.save(port);
62 | }
63 |
64 | @ResponseBody
65 | @RequestMapping(value = "batchDelete", method = RequestMethod.POST)
66 | public ApiResponse batchDeleteUserPort(@RequestBody PortAddDTO port) {
67 | if(WebCurrentData.getUser().getUserType()>0){
68 | return ApiResponse.error("403", "您没有权限执行此操作");
69 | }
70 | return portService.batchDelete(port);
71 | }
72 |
73 | @ResponseBody
74 | @GetMapping("delete")
75 | public ApiResponse delete(Integer id) {
76 | if(WebCurrentData.getUser().getUserType()>0){
77 | return ApiResponse.error("403", "您没有权限执行此操作");
78 | }
79 | return portService.delete(id);
80 | }
81 |
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.model.Resource;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.ResponseBody;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | /**
16 | * 资源管理
17 | */
18 | @RestController
19 | public class ResourceController {
20 |
21 | private static Map> USER_TYPE_RESOURCE = new HashMap<>();
22 |
23 | /**
24 | * 初始化权限
25 | */
26 | static {
27 | List adminResourceList = new ArrayList<>();
28 | adminResourceList.add(new Resource(1, "看板", "/dashboard", "dashboard"));
29 | adminResourceList.add(new Resource(2, "服务器管理", "/server", "el-icon-cpu"));
30 | // adminResourceList.add(new Resource(3, "端口管理", "/port", "el-icon-s-help"));
31 | adminResourceList.add(new Resource(4, "账号管理", "/user", "el-icon-user-solid"));
32 | adminResourceList.add(new Resource(5, "中转管理", "/forward", "el-icon-attract"));
33 | adminResourceList.add(new Resource(6, "配置文件", "/config", "el-icon-tickets"));
34 | adminResourceList.add(new Resource(7, "系统设置", "/system", "el-icon-s-tools"));
35 | // adminResourceList.add(new Resource(7, "更新记录", "/system", "el-icon-notebook-2"));
36 | adminResourceList.add(new Resource(8, "打赏", "/reward", "el-icon-sugar"));
37 |
38 |
39 | USER_TYPE_RESOURCE.put(0, adminResourceList);
40 | List userResourceList = new ArrayList<>();
41 | userResourceList.add(new Resource(1, "看板", "/dashboard", "dashboard"));
42 | userResourceList.add(new Resource(5, "中转管理", "/forward", "el-icon-attract"));
43 | userResourceList.add(new Resource(6, "配置文件", "/config", "el-icon-tickets"));
44 | // userResourceList.add(new Resource(6, "更新记录", "/config", "el-icon-notebook-2"));
45 | userResourceList.add(new Resource(8, "打赏", "/reward", "el-icon-sugar"));
46 | USER_TYPE_RESOURCE.put(1, userResourceList);
47 | }
48 |
49 | /**
50 | * 获取资源
51 | *
52 | * @return
53 | */
54 | @GetMapping("/getMenus")
55 | public ApiResponse getResource() {
56 | Integer userType = WebCurrentData.getUser().getUserType();
57 | return ApiResponse.ok(USER_TYPE_RESOURCE.get(userType));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/ServerController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
6 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
7 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
8 | import com.leeroy.forwordpanel.forwordpanel.service.PortService;
9 | import com.leeroy.forwordpanel.forwordpanel.service.ServerService;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Controller;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | @RequestMapping("server")
15 | @Controller
16 | public class ServerController {
17 |
18 | @Autowired
19 | private ServerService serverService;
20 |
21 |
22 | @ResponseBody
23 | @PostMapping("getPage")
24 | public ApiResponse getPage(@RequestBody PageRequest pageRequest) {
25 | return ApiResponse.ok(serverService.getServerPage(pageRequest));
26 | }
27 |
28 |
29 | @ResponseBody
30 | @GetMapping("getList")
31 | public ApiResponse getList() {
32 | return ApiResponse.ok(serverService.findList());
33 | }
34 |
35 |
36 | @ResponseBody
37 | @GetMapping("getForwardServerList")
38 | public ApiResponse getForwardServerList(Integer userId) {
39 | return ApiResponse.ok(serverService.getForwardServerList(userId));
40 | }
41 |
42 | @ResponseBody
43 | @RequestMapping(value = "save", method = RequestMethod.POST)
44 | public ApiResponse saveUserPort(@RequestBody Server server) {
45 | if(WebCurrentData.getUser().getUserType()>0){
46 | return ApiResponse.error("403", "您没有权限执行此操作");
47 | }
48 | return serverService.save(server);
49 | }
50 |
51 | @ResponseBody
52 | @GetMapping("delete")
53 | public ApiResponse delete(Integer id) {
54 | if(WebCurrentData.getUser().getUserType()>0){
55 | return ApiResponse.error("403", "您没有权限执行此操作");
56 | }
57 | return serverService.delete(id);
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/SysConfigController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.PortAddDTO;
7 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
8 | import com.leeroy.forwordpanel.forwordpanel.model.SysConfig;
9 | import com.leeroy.forwordpanel.forwordpanel.service.PortService;
10 | import com.leeroy.forwordpanel.forwordpanel.service.SysConfigService;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Controller;
13 | import org.springframework.web.bind.annotation.*;
14 |
15 | @RequestMapping("sysConfig")
16 | @Controller
17 | public class SysConfigController {
18 |
19 | @Autowired
20 | private SysConfigService sysConfigService;
21 |
22 |
23 | @ResponseBody
24 | @RequestMapping(value = "save", method = RequestMethod.POST)
25 | public ApiResponse saveUserPort(@RequestBody SysConfig sysConfig) {
26 | if (WebCurrentData.getUser().getUserType() > 0) {
27 | return ApiResponse.error("403", "您没有权限执行此操作");
28 | }
29 | return sysConfigService.save(sysConfig);
30 | }
31 |
32 | @ResponseBody
33 | @GetMapping("getSysConfig")
34 | public ApiResponse delete() {
35 | return sysConfigService.getConfig();
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/SystemController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
4 | import com.leeroy.forwordpanel.forwordpanel.service.DataUpgradeService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 | import org.springframework.web.multipart.MultipartFile;
11 |
12 | /**
13 | * @program: forwordpanel
14 | * @description: 系统设置
15 | * @author: liruifeng
16 | * @created: 2020/09/20 13:38
17 | */
18 | @RequestMapping("system")
19 | @RestController
20 | public class SystemController {
21 |
22 | @Autowired
23 | private DataUpgradeService upgradeService;
24 |
25 | /**
26 | * 导出数据库
27 | */
28 | @GetMapping("exportData")
29 | public ApiResponse exportData(){
30 | return upgradeService.exportData();
31 | }
32 |
33 | /**
34 | * 导入数据库
35 | * @param file
36 | * @return
37 | */
38 | @PostMapping("importData")
39 | public ApiResponse exportDB(MultipartFile file){
40 | return upgradeService.importData(file);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 |
4 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
5 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.UserPortDTO;
7 | import com.leeroy.forwordpanel.forwordpanel.dto.UserSearchDTO;
8 | import com.leeroy.forwordpanel.forwordpanel.model.User;
9 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortService;
10 | import com.leeroy.forwordpanel.forwordpanel.service.UserService;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Controller;
15 | import org.springframework.util.CollectionUtils;
16 | import org.springframework.web.bind.annotation.*;
17 |
18 | import java.util.HashMap;
19 | import java.util.List;
20 | import java.util.Map;
21 |
22 | /**
23 | * 用户管理
24 | */
25 | @Controller
26 | @RequestMapping("user")
27 | public class UserController {
28 |
29 | private Logger logger = LoggerFactory.getLogger(this.getClass());
30 |
31 | @Autowired
32 | private UserService userService;
33 |
34 | @Autowired
35 | private UserPortService userPortService;
36 |
37 |
38 | /**
39 | * 设置密码
40 | *
41 | * @param pwd
42 | * @param isPwd
43 | * @return
44 | */
45 | @RequestMapping("setPwd")
46 | @ResponseBody
47 | public ApiResponse setPassword(String pwd, String isPwd) {
48 | logger.info("进行密码重置");
49 | Map data = new HashMap();
50 | if (!pwd.equals(isPwd)) {
51 | return ApiResponse.error("400", "两次密码不一致");
52 | }
53 | //获取当前登陆的用户信息
54 | User user = WebCurrentData.getUser();
55 | userService.updatePwd(user.getUsername(), pwd);
56 | return ApiResponse.ok();
57 | }
58 |
59 | /**
60 | * 功能描述: 跳到系统用户列表
61 | *
62 | * @param:
63 | * @return:
64 | * @auther: youqing
65 | * @date: 2018/11/21 13:50
66 | */
67 | @RequestMapping("/userManage")
68 | public String userManage() {
69 | return "user/userManage";
70 | }
71 |
72 | /**
73 | * 用户分页
74 | *
75 | * @param userSearch
76 | * @return
77 | */
78 | @RequestMapping(value = "/getPage", method = RequestMethod.POST)
79 | @ResponseBody
80 | public ApiResponse getUserPage(@RequestBody UserSearchDTO userSearch) {
81 | // 获取用户列表
82 | return ApiResponse.ok(userService.getUserPage(userSearch));
83 | }
84 |
85 | /**
86 | * 用户列表
87 | *
88 | * @param userSearch
89 | * @return
90 | */
91 | @RequestMapping(value = "/getList", method = RequestMethod.POST)
92 | @ResponseBody
93 | public ApiResponse getUserList(@RequestBody UserSearchDTO userSearch) {
94 | // 获取用户列表
95 | return ApiResponse.ok(userService.getUserList(userSearch));
96 | }
97 |
98 |
99 | /**
100 | * 新增/更新用户
101 | *
102 | * @param user
103 | * @return
104 | */
105 | @RequestMapping(value = "/save", method = RequestMethod.POST)
106 | @ResponseBody
107 | public ApiResponse setUser(@RequestBody User user) {
108 | logger.info("设置用户[新增或更新]!user:" + user);
109 | if (user.getId() == null) {
110 | return userService.addUser(user);
111 | } else {
112 | return userService.updateUser(user);
113 | }
114 | }
115 |
116 |
117 | /**
118 | * 禁用用户
119 | *
120 | * @param id
121 | * @return
122 | */
123 | @RequestMapping(value = "/disable", method = RequestMethod.GET)
124 | @ResponseBody
125 | public ApiResponse disable(@RequestParam("id") Integer id) {
126 | if (WebCurrentData.getUser().getUserType() > 0) {
127 | return ApiResponse.error("403", "您没有权限执行此操作");
128 | }
129 | return userService.disableUser(id);
130 | }
131 |
132 | /**
133 | * 启用用户
134 | *
135 | * @param id
136 | * @return
137 | */
138 | @RequestMapping(value = "/enable", method = RequestMethod.GET)
139 | @ResponseBody
140 | public ApiResponse enable(@RequestParam("id") Integer id) {
141 | if (WebCurrentData.getUser().getUserType() > 0) {
142 | return ApiResponse.error("403", "您没有权限执行此操作");
143 | }
144 | return userService.enableUser(id);
145 | }
146 |
147 | /**
148 | * 获取用户信息
149 | *
150 | * @return
151 | */
152 | @RequestMapping(value = "/getCurrentUser", method = RequestMethod.GET)
153 | @ResponseBody
154 | public ApiResponse getCurrentUser() {
155 | return ApiResponse.ok(userService.getCurrentUser());
156 | }
157 |
158 | /**
159 | * 启用用户
160 | *
161 | * @param id
162 | * @return
163 | */
164 | @GetMapping(value = "/delete")
165 | @ResponseBody
166 | public ApiResponse delete(@RequestParam("id") Integer id) {
167 | if (WebCurrentData.getUser().getUserType() > 0) {
168 | return ApiResponse.error("403", "您没有权限执行此操作");
169 | }
170 | List userPortList = userPortService.findUserPortList(id);
171 | if (!CollectionUtils.isEmpty(userPortList)) {
172 | return ApiResponse.error("401", "请先删除用户端口");
173 | }
174 | return userService.delUser(id);
175 | }
176 |
177 | /**
178 | * 启用用户
179 | *
180 | * @param id
181 | * @return
182 | */
183 | @GetMapping(value = "/resetFlow")
184 | @ResponseBody
185 | public ApiResponse resetFlow(@RequestParam("id") Integer id) {
186 | if (WebCurrentData.getUser().getUserType() > 0) {
187 | return ApiResponse.error("403", "您没有权限执行此操作");
188 | }
189 | return userService.resetUserFlow(id);
190 | }
191 |
192 | /**
193 | * 获取用户流量信息
194 | *
195 | * @param userId
196 | * @return
197 | */
198 | @GetMapping(value = "/getUserDetail")
199 | @ResponseBody
200 | public ApiResponse getUserDetail(@RequestParam(value = "userId", required = false) Integer userId) {
201 | return ApiResponse.ok(userService.getUserDetail(userId));
202 | }
203 |
204 | /**
205 | * 获取用户详细流量信息
206 | *
207 | * @param userId
208 | * @return
209 | */
210 | @GetMapping(value = "/getForwardFlow")
211 | @ResponseBody
212 | public ApiResponse getForwardFlow(@RequestParam(value = "userId", required = false) Integer userId) {
213 | return ApiResponse.ok(userService.getForwardFlow(userId));
214 | }
215 |
216 | /**
217 | * 获取用户详细流量信息
218 | *
219 | * @param forwardId
220 | * @return
221 | */
222 | @GetMapping(value = "/getPortForwardFlow")
223 | @ResponseBody
224 | public ApiResponse getPortForwardFlow(@RequestParam(value = "forwardId", required = false) Integer forwardId) {
225 | return ApiResponse.ok(userService.getPortForwardFlow(forwardId));
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/UserPortController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 |
4 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
5 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
6 | import com.leeroy.forwordpanel.forwordpanel.common.response.PageDataResult;
7 | import com.leeroy.forwordpanel.forwordpanel.common.response.ResponseResult;
8 | import com.leeroy.forwordpanel.forwordpanel.dto.UserPortPageRequest;
9 | import com.leeroy.forwordpanel.forwordpanel.model.UserPort;
10 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortService;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Controller;
13 | import org.springframework.stereotype.Service;
14 | import org.springframework.web.bind.annotation.*;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * @Title: UserController
20 | * @Description: 系统用户管理
21 | * @author: youqing
22 | * @version: 1.0
23 | * @date: 2018/11/20 15:17
24 | */
25 | @RestController
26 | @RequestMapping("userport")
27 | public class UserPortController {
28 |
29 | @Autowired
30 | private UserPortService userPortService;
31 |
32 | @PostMapping("getList")
33 | public ApiResponse getUserPortList(@RequestBody UserPortPageRequest pageRequest) {
34 | return ApiResponse.ok(userPortService.findUserPortList(pageRequest));
35 | }
36 |
37 | @PostMapping("save")
38 | public ApiResponse saveUserPort(@RequestBody List userPortList) {
39 | if(WebCurrentData.getUser().getUserType()>0){
40 | return ApiResponse.error("403", "您没有权限执行此操作");
41 | }
42 | return userPortService.save(userPortList);
43 | }
44 |
45 | @GetMapping("delete")
46 | public ApiResponse delete(Integer id) {
47 | if(WebCurrentData.getUser().getUserType()>0){
48 | return ApiResponse.error("403", "您没有权限执行此操作");
49 | }
50 | userPortService.delUserPort(id);
51 | return ApiResponse.ok();
52 | }
53 |
54 | /**
55 | * 禁用用户
56 | *
57 | * @param id
58 | * @return
59 | */
60 | @RequestMapping(value = "/disable", method = RequestMethod.GET)
61 | @ResponseBody
62 | public ApiResponse disable(@RequestParam("id") Integer id) {
63 | if(WebCurrentData.getUser().getUserType()>0){
64 | return ApiResponse.error("403", "您没有权限执行此操作");
65 | }
66 | return userPortService.disablePort(id);
67 | }
68 |
69 | /**
70 | * 启用用户
71 | *
72 | * @param id
73 | * @return
74 | */
75 | @RequestMapping(value = "/enable", method = RequestMethod.GET)
76 | @ResponseBody
77 | public ApiResponse enable(@RequestParam("id") Integer id) {
78 | if(WebCurrentData.getUser().getUserType()>0){
79 | return ApiResponse.error("403", "您没有权限执行此操作");
80 | }
81 | return userPortService.enablePort(id);
82 | }
83 |
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/controller/UserPortForwardController.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.controller;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
4 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
5 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.UserPortForwardPageReq;
7 | import com.leeroy.forwordpanel.forwordpanel.model.User;
8 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
9 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortForwardService;
10 | import com.leeroy.forwordpanel.forwordpanel.service.UserService;
11 | import org.apache.commons.lang3.time.DateFormatUtils;
12 | import org.apache.commons.lang3.time.DateUtils;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Controller;
15 | import org.springframework.ui.Model;
16 | import org.springframework.web.bind.annotation.*;
17 |
18 | @RequestMapping("forward")
19 | @Controller
20 | public class UserPortForwardController {
21 |
22 | @Autowired
23 | private UserPortForwardService forwardService;
24 |
25 | /**
26 | * 中转列表
27 | *
28 | * @return
29 | */
30 | @ResponseBody
31 | @PostMapping("getPage")
32 | public ApiResponse getList(@RequestBody UserPortForwardPageReq pageRequest) {
33 | return forwardService.getUserForwardList(pageRequest);
34 | }
35 |
36 | /**
37 | * 开始中转
38 | *
39 | * @param userPortForward
40 | * @return
41 | */
42 | @ResponseBody
43 | @PostMapping("start")
44 | public ApiResponse startForward(@RequestBody UserPortForward userPortForward) {
45 | userPortForward.setUserId(userPortForward.getUserId()==null?WebCurrentData.getUserId():userPortForward.getUserId());
46 | return forwardService.startForward(userPortForward, true);
47 | }
48 |
49 | /**
50 | * 停止中转
51 | *
52 | * @param userPortForward
53 | * @return
54 | */
55 | @ResponseBody
56 | @PostMapping("stop")
57 | public ApiResponse stopFroward(@RequestBody UserPortForward userPortForward) {
58 | userPortForward.setUserId(WebCurrentData.getUserId());
59 | return forwardService.stopForward(userPortForward);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/ClashDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Clash;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserPort;
6 | import org.apache.ibatis.annotations.Update;
7 |
8 | public interface ClashDao extends BaseMapper {
9 |
10 |
11 | @Update("update clash set disabled=#{disabled} where id=#{id}")
12 | void updateDisable(Boolean disabled, Integer id);
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/ForwardFlowDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.ForwardFlow;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
6 | import org.apache.ibatis.annotations.Mapper;
7 | import org.apache.ibatis.annotations.Update;
8 |
9 | @Mapper
10 | public interface ForwardFlowDao extends BaseMapper {
11 |
12 |
13 | @Update("update forward_flow set disabled=#{disabled} where id=#{id}")
14 | void updateDisable(Boolean disabled, Integer id);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/PortDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
5 | import org.apache.ibatis.annotations.Select;
6 | import org.apache.ibatis.annotations.Update;
7 |
8 | import java.util.List;
9 |
10 | public interface PortDao extends BaseMapper {
11 |
12 |
13 | @Update("update port set disabled=#{disabled} where id=#{id}")
14 | void updateDisable(Boolean disabled, Integer id);
15 |
16 | @Select("select a.* from port a where not exists (select 1 from user_port up where up.port_id = a.id and up.deleted=0) and a.deleted=0 and a.server_id = #{serverId} order by a.create_time desc")
17 | List selectServerFreePort(Integer serverId);
18 |
19 | @Update("delete from port where local_port>= #{startPort} and local_port <=#{endPort} and server_id = #{serverId}")
20 | void batchDelete(Integer startPort, Integer endPort, Integer serverId);
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/ServerDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
5 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
6 | import org.apache.ibatis.annotations.Select;
7 | import org.apache.ibatis.annotations.Update;
8 |
9 | import java.util.List;
10 |
11 | public interface ServerDao extends BaseMapper {
12 |
13 |
14 | @Update("update server set disabled=#{disabled} where id=#{id}")
15 | void updateDisable(Boolean disabled, Integer id);
16 |
17 |
18 | @Select("select s.* from server s, user_server us where s.id = us.server_id and s.deleted = false and us.deleted = false and us.user_id =#{userId} ")
19 | List selectUserServer(Integer userId);
20 |
21 | @Select("select s.* from server s where exists ( select 1 from user_port_forward upf where s.id = upf.server_id and s.deleted = false and upf.deleted = false and upf.user_id =#{userId}) ")
22 | List selectForwardServer(Integer userId);
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/SysConfigDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.SysConfig;
5 |
6 | public interface SysConfigDao extends BaseMapper {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/UserDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.dto.UserSearchDTO;
5 | import com.leeroy.forwordpanel.forwordpanel.model.User;
6 | import org.apache.ibatis.annotations.Mapper;
7 | import org.apache.ibatis.annotations.Select;
8 | import org.apache.ibatis.annotations.Update;
9 |
10 | import java.util.List;
11 |
12 | @Mapper
13 | public interface UserDao extends BaseMapper {
14 |
15 |
16 | @Select("")
37 | List getUsers(UserSearchDTO userSearch);
38 |
39 | @Select("")
46 | User getUserByUserName(String username, Integer id);
47 |
48 | @Update("update sys_user set password=#{password} where username=#{username}")
49 | void updatePwd(String username, String password);
50 |
51 | @Update("update sys_user set disabled=#{disabled} where id=#{id}")
52 | void updateDisable(Boolean disabled, Integer id);
53 |
54 | @Update("update sys_user set deleted=true where id=#{id}")
55 | void deleteUser(Integer id);
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/UserPortDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserPort;
6 | import org.apache.ibatis.annotations.Select;
7 | import org.apache.ibatis.annotations.Update;
8 |
9 | import java.util.List;
10 |
11 | public interface UserPortDao extends BaseMapper {
12 |
13 |
14 | @Update("update user_port set disabled=#{disabled} where id=#{id}")
15 | void updateDisable(Boolean disabled, Integer id);
16 |
17 | @Select("select p.* from user_port up, port p where up.port_id = p.id and up.deleted = false and p.deleted = false and p.local_port=#{localPort} and p.server_id =#{serverId}")
18 | List selectByLocalPort(Integer localPort, Integer serverId);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/UserPortForwardDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
5 | import org.apache.ibatis.annotations.Mapper;
6 | import org.apache.ibatis.annotations.Update;
7 |
8 | @Mapper
9 | public interface UserPortForwardDao extends BaseMapper {
10 |
11 |
12 | @Update("update user_port_forward set disabled=#{disabled} where id=#{id}")
13 | void updateDisable(Boolean disabled, Integer id);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/UserServerDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserServer;
6 | import org.apache.ibatis.annotations.Update;
7 |
8 | public interface UserServerDao extends BaseMapper {
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dao/UserTokenDao.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserToken;
5 |
6 | public interface UserTokenDao extends BaseMapper {
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/ClashNodeBase.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @program: forwordpanel
7 | * @description: clash node
8 | * @author: liruifeng
9 | * @created: 2020/09/30 14:01
10 | */
11 | @Data
12 | public class ClashNodeBase {
13 |
14 | protected String name;
15 | protected String server;
16 | protected String port;
17 | protected String type;
18 | protected String password;
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/ClashNodeTrojan.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @program: forwordpanel
7 | * @description: clash node
8 | * @author: liruifeng
9 | * @created: 2020/09/30 14:01
10 | */
11 | @Data
12 | public class ClashNodeTrojan extends ClashNodeBase {
13 |
14 | private String sni;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/DataFlow.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class DataFlow {
7 | public DataFlow(String tcp, String udp) {
8 | this.tcp = tcp;
9 | this.udp = udp;
10 | }
11 |
12 | private String tcp;
13 | private String udp;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/ForwardFlowDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 |
7 | import javax.persistence.Entity;
8 | import javax.persistence.Id;
9 | import java.util.Date;
10 |
11 | /**
12 | * @program: forwordpanel
13 | * @description: 用户中转流量记录
14 | * @author: liruifeng
15 | * @created: 2020/09/17 14:06
16 | */
17 | @Data
18 | public class ForwardFlowDTO {
19 |
20 | @Id
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 | //中转记录id
24 | private Integer forwardId;
25 | // 中转用户
26 | private Integer userId;
27 | //端口id
28 | private Integer portId;
29 | // 服务id
30 | private Integer serverId;
31 | // 服务名称
32 | private String serverName;
33 | // 本地端口
34 | private Integer localPort;
35 | // 远程端口
36 | private Integer internetPort;
37 | // 目标ip
38 | private String remoteIp;
39 | // 目标主机地址
40 | private String remoteHost;
41 | // 流量使用量
42 | private Long dataUsage;
43 | // 目标主机端口
44 | private Integer remotePort;
45 | // 创建时间
46 | private Date createTime;
47 | //更新时间
48 | private Date updateTime;
49 | //删除表示
50 | private Boolean deleted;
51 | //禁用表示
52 | private Boolean disabled;
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/LoginDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 |
4 |
5 | /**
6 | * @Title: UserDTO
7 | * @Description:
8 | * @author: youqing
9 | * @version: 1.0
10 | * @date: 2018/11/21 11:19
11 | */
12 | public class LoginDTO {
13 | private String username;
14 |
15 | private String password;
16 |
17 | private String rememberMe;
18 |
19 | public String getUsername() {
20 | return username;
21 | }
22 |
23 | public void setUsername(String username) {
24 | this.username = username;
25 | }
26 |
27 | public String getPassword() {
28 | return password;
29 | }
30 |
31 | public void setPassword(String password) {
32 | this.password = password;
33 | }
34 |
35 | public String getRememberMe() {
36 | return rememberMe;
37 | }
38 |
39 | public void setRememberMe(String rememberMe) {
40 | this.rememberMe = rememberMe;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return "LoginDTO{" +
46 | "username='" + username + '\'' +
47 | ", password='" + password + '\'' +
48 | ", rememberMe='" + rememberMe + '\'' +
49 | '}';
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/PageRequest.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 |
4 | /**
5 | * @Title:
6 | * @Description:
7 | * @author: chris
8 | * @version:
9 | * @date: 2018/10/23 11:46
10 | */
11 | public class PageRequest {
12 | /** 默认页面大小 */
13 | public static Integer DEFAULT_PAGE_SIZE = 10;
14 |
15 | /** 默认页码 */
16 | public static Integer DEFAULT_PAGE_NUM = 1;
17 |
18 | protected Integer pageNum;
19 | protected Integer pageSize;
20 |
21 |
22 | public Integer getPageNum() {
23 | return pageNum <= 0 ? DEFAULT_PAGE_NUM : pageNum;
24 | }
25 |
26 | public void setPageNum(int pageNum) {
27 | this.pageNum = pageNum;
28 | }
29 |
30 | public Integer getPageSize() {
31 | return pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize;
32 | }
33 |
34 | public void setPageSize(int pageSize) {
35 | this.pageSize = pageSize;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/PortAddDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * 端口信息
7 | */
8 | @Data
9 | public class PortAddDTO {
10 |
11 |
12 | /**
13 | * 所属服务器
14 | */
15 | private Integer serverId;
16 |
17 | /**
18 | * 本地端口
19 | */
20 | private String localPort;
21 |
22 | /**
23 | * 外网端口
24 | */
25 | private String internetPort;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/PortDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import java.util.Date;
10 |
11 | /**
12 | * 端口信息
13 | */
14 | @Data
15 | public class PortDTO {
16 | @TableId(value = "id", type = IdType.AUTO)
17 | private Integer id;
18 |
19 | /**
20 | * 所属服务器
21 | */
22 | private Integer serverId;
23 |
24 | /**
25 | * 服务器名称
26 | */
27 | private String serverName;
28 |
29 | /**
30 | * 服务起ip
31 | */
32 | private String serverHost;
33 |
34 | /**
35 | * 本地端口
36 | */
37 | private Integer localPort;
38 |
39 | /**
40 | * 外网端口
41 | */
42 | private Integer internetPort;
43 |
44 | @DateTimeFormat(pattern = "yyyy-MM-dd")
45 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
46 | private Date createTime;
47 |
48 | @DateTimeFormat(pattern = "yyyy-MM-dd")
49 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
50 | private Date updateTime;
51 |
52 | private Boolean deleted;
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/PortPageRequest.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @program: forwordpanel
7 | * @description: 端口分页请求
8 | * @author: liruifeng
9 | * @created: 2020/10/14 12:51
10 | */
11 | @Data
12 | public class PortPageRequest extends PageRequest{
13 |
14 | private Integer serverId;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import lombok.Data;
8 |
9 | import java.util.Date;
10 |
11 |
12 | @TableName("sys_user")
13 | @Data
14 | public class UserDTO {
15 | /**
16 | * ID
17 | */
18 | @TableId(value = "id", type = IdType.AUTO)
19 | private Integer id;
20 |
21 | /**
22 | * 系统用户名称
23 | */
24 | @TableField("username")
25 | private String username;
26 |
27 | /**
28 | * 系统用户密码
29 | */
30 | private String password;
31 |
32 | /**
33 | * 手机号
34 | */
35 | private String userPhone;
36 |
37 | /**
38 | * 手机号
39 | */
40 | private String telegram;
41 |
42 |
43 | /**
44 | * 登记时间
45 | */
46 | private Date regTime;
47 |
48 | /**
49 | * 状态(0:无效;1:有效)
50 | */
51 | private Boolean disabled;
52 |
53 | /**
54 | * 删除表示
55 | */
56 | private Boolean deleted;
57 |
58 | /**
59 | * 用户流量限制
60 | */
61 | private Long dataLimit;
62 |
63 | /**
64 | * 流量使用量
65 | */
66 | private Long dataUsage;
67 |
68 | /**
69 | * 用户类型
70 | */
71 | private Integer userType;
72 |
73 | /**
74 | * 到期时间
75 | */
76 | private Date expireTime;
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserPortDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 |
4 | import com.baomidou.mybatisplus.annotation.IdType;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.fasterxml.jackson.annotation.JsonFormat;
7 | import lombok.Data;
8 | import org.springframework.format.annotation.DateTimeFormat;
9 |
10 | import java.util.Date;
11 |
12 | /**
13 | * 端口
14 | */
15 | @Data
16 | public class UserPortDTO {
17 | @TableId(value = "id",type = IdType.AUTO)
18 | private Integer id;
19 | private Integer userId;
20 | private Integer portId;
21 | private Integer localPort;
22 | private Boolean disabled;
23 | private Boolean deleted;
24 | /**
25 | * 端口流量限制
26 | */
27 | private Long dataLimit;
28 | /**
29 | * 到期时间
30 | */
31 | @DateTimeFormat(pattern = "yyyy-MM-dd")
32 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
33 | private Date expireTime;
34 |
35 | @DateTimeFormat(pattern = "yyyy-MM-dd")
36 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
37 | private Date createTime;
38 |
39 | @DateTimeFormat(pattern = "yyyy-MM-dd")
40 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
41 | private Date updateTime;
42 |
43 | /**
44 | * 所属服务器
45 | */
46 | private Integer serverId;
47 |
48 | /**
49 | * 服务器名称
50 | */
51 | private String serverName;
52 |
53 | /**
54 | * 服务起ip
55 | */
56 | private String serverHost;
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserPortForwardDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import java.util.Date;
10 |
11 | /**
12 | * 端口转发实体
13 | */
14 | @Data
15 | public class UserPortForwardDTO {
16 |
17 | @TableId(value = "id", type = IdType.AUTO)
18 | private Integer id;
19 | // 中转用户
20 | private Integer userId;
21 | //端口id
22 | private Integer portId;
23 | private Integer serverId;
24 | private Integer localPort;
25 | private String serverName;
26 | private String serverHost;
27 | private Integer internetPort;
28 | private String username;
29 | // 目标ip
30 | private String remoteIp;
31 | // 目标主机地址
32 | private String remoteHost;
33 | // 流量使用量
34 | private Long dataUsage;
35 | // 目标主机端口
36 | private Integer remotePort;
37 | // 创建时间
38 | @DateTimeFormat(pattern = "yyyy-MM-dd")
39 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
40 | private Date createTime;
41 | //更新时间
42 | @DateTimeFormat(pattern = "yyyy-MM-dd")
43 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
44 | private Date updateTime;
45 | //删除表示
46 | private Boolean deleted;
47 | //禁用表示
48 | private Boolean disabled;
49 |
50 | private Integer state;
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserPortForwardPageReq.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @program: forwordpanel
7 | * @description: 中转分页查询
8 | * @author: liruifeng
9 | * @created: 2020/10/13 09:24
10 | */
11 | @Data
12 | public class UserPortForwardPageReq extends PageRequest {
13 | private Integer userId;
14 | private Integer serverId;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserPortPageRequest.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @program: forwordpanel
7 | * @description: 端口分页请求
8 | * @author: liruifeng
9 | * @created: 2020/10/14 12:51
10 | */
11 | @Data
12 | public class UserPortPageRequest extends PageRequest{
13 |
14 | private Integer userId;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/dto/UserSearchDTO.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.dto;
2 |
3 |
4 | import lombok.Data;
5 |
6 | /**
7 | * @Title: UserSearchDTO
8 | * @Description:
9 | * @author: youqing
10 | * @version: 1.0
11 | * @date: 2018/11/21 11:19
12 | */
13 | @Data
14 | public class UserSearchDTO extends PageRequest {
15 | private String username;
16 |
17 | private String userPhone;
18 |
19 | private String telegram;
20 |
21 | private Boolean disabled;
22 |
23 | private Integer id;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/job/CheckDDNSJob.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.job;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.dao.PortDao;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
6 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortForwardService;
7 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortService;
8 | import com.leeroy.forwordpanel.forwordpanel.service.UserService;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.beans.factory.annotation.Configurable;
12 | import org.springframework.scheduling.annotation.EnableScheduling;
13 | import org.springframework.scheduling.annotation.Scheduled;
14 | import org.springframework.stereotype.Component;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * 检查用户转发ddns变化
20 | */
21 | @Slf4j
22 | @EnableScheduling
23 | @Configurable
24 | @Component
25 | public class CheckDDNSJob {
26 |
27 | @Autowired
28 | private UserService userService;
29 |
30 | @Autowired
31 | private UserPortService userPortService;
32 | @Autowired
33 | private PortDao portDao;
34 | @Autowired
35 | private UserPortForwardService userPortForwardService;
36 |
37 | @Scheduled(cron = "0 0/3 * * * ?")
38 | public void execute() {
39 | List userPortForwards = userPortForwardService.getUsingForwards();
40 | for(UserPortForward forward: userPortForwards){
41 | log.info(">>>>开始执行DDNS检查任务");
42 | String remoteIp = userPortForwardService.getRemoteIp(forward.getRemoteHost());
43 | if (remoteIp == null) {
44 | userPortForwardService.stopForward(forward);
45 | } else if (!remoteIp.equals(forward.getRemoteIp())) {
46 | Port port = portDao.selectById(forward.getPortId());
47 | forward.setRemoteIp(remoteIp);
48 | userPortForwardService.updateForward(forward, port);
49 | }
50 | log.info(">>>>结束执行DDNS检查任务");
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/job/CheckExpireJob.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.job;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.User;
4 | import com.leeroy.forwordpanel.forwordpanel.service.ForwardFlowService;
5 | import com.leeroy.forwordpanel.forwordpanel.service.ForwardService;
6 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortService;
7 | import com.leeroy.forwordpanel.forwordpanel.service.UserService;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.annotation.Configurable;
10 | import org.springframework.scheduling.annotation.EnableScheduling;
11 | import org.springframework.scheduling.annotation.Scheduled;
12 | import org.springframework.stereotype.Component;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * 检查用户账户到期的任务
18 | */
19 | @EnableScheduling
20 | @Configurable
21 | @Component
22 | public class CheckExpireJob {
23 |
24 | @Autowired
25 | private UserService userService;
26 |
27 | @Autowired
28 | private UserPortService userPortService;
29 |
30 | @Autowired
31 | private ForwardFlowService forwardFlowService;
32 |
33 | @Scheduled(cron = "0 0/1 * * * ?")
34 | public void execute() {
35 | List expireUserList = userService.findExpireUserList();
36 | for (User user : expireUserList) {
37 | if (user.getExpireTime() == null||user.getUserType()<=0) {
38 | continue;
39 | }
40 | userPortService.disableUserPort(user.getId());
41 | userService.disableUserById(user.getId());
42 | }
43 | //流量用超的用户
44 | List enableUserList = userService.findEnableUserList();
45 | for (User user : enableUserList) {
46 | if ( user.getDataLimit() == null || user.getDataLimit() <= 0L || user.getUserType()<=0) {
47 | continue;
48 | }
49 | Long total = forwardFlowService.getUserFlowTotal(user.getId());
50 | if (total >= user.getDataLimit() * 1024 * 1024 * 1024) {
51 | userPortService.disableUserPort(user.getId());
52 | userService.disableUserById(user.getId());
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/job/DataUsageJob.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.job;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.User;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
5 | import com.leeroy.forwordpanel.forwordpanel.service.ForwardFlowService;
6 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortForwardService;
7 | import com.leeroy.forwordpanel.forwordpanel.service.UserService;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.annotation.Configurable;
10 | import org.springframework.scheduling.annotation.EnableScheduling;
11 | import org.springframework.scheduling.annotation.Scheduled;
12 | import org.springframework.stereotype.Component;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * 统计用户使用的流量
18 | */
19 | @EnableScheduling
20 | @Configurable
21 | @Component
22 | public class DataUsageJob {
23 |
24 | @Autowired
25 | private UserService userService;
26 |
27 | @Autowired
28 | private UserPortForwardService userPortForwardService;
29 |
30 | @Autowired
31 | private ForwardFlowService forwardFlowService;
32 |
33 |
34 | @Scheduled(cron = "0 0/3 * * * ?")
35 | public void execute() {
36 | List expireUserList = userService.findEnableUserList();
37 | expireUserList.forEach(user -> {
38 | List userForwardList = userPortForwardService.findUserForwardList(user.getId());
39 | forwardFlowService.collectForwardFlow(userForwardList);
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/job/KeepForwardJob.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.job;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.enums.ServerStatusEnum;
4 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
5 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
6 | import com.leeroy.forwordpanel.forwordpanel.service.RemoteForwardService;
7 | import com.leeroy.forwordpanel.forwordpanel.service.ServerService;
8 | import com.leeroy.forwordpanel.forwordpanel.service.UserPortForwardService;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.beans.factory.annotation.Configurable;
12 | import org.springframework.scheduling.annotation.EnableScheduling;
13 | import org.springframework.scheduling.annotation.Scheduled;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.util.StringUtils;
16 |
17 | import java.util.List;
18 |
19 | /**
20 | * @program: forwordpanel
21 | * @description: 保持中转任务
22 | * @author: liruifeng
23 | * @created: 2020/09/24 15:06
24 | */
25 | @EnableScheduling
26 | @Configurable
27 | @Component
28 | @Slf4j
29 | public class KeepForwardJob {
30 |
31 | @Autowired
32 | ServerService serverService;
33 |
34 | @Autowired
35 | RemoteForwardService remoteForwardService;
36 |
37 | @Autowired
38 | UserPortForwardService userPortForwardService;
39 |
40 | @Scheduled(cron = "0 0/3 * * * ?")
41 | public void execute() {
42 | log.info(">>>>开始执行中转机重启检查任务");
43 | List serviceList = serverService.findListWithoutLogin();
44 | for (Server server : serviceList) {
45 | remoteForwardService.checkIPV4Forward(server);
46 | String lastRestart = remoteForwardService.getLastRestart(server);
47 | log.info(">>>>服务器:{} 当前重启时间:{}, 记录重启时间:{}", server.getServerName(), lastRestart, server.getLastRebootTime());
48 | if(StringUtils.isEmpty(lastRestart)){
49 | server.setState(ServerStatusEnum.CONNECT_FAIL.getCode());
50 | serverService.save(server);
51 | continue;
52 | }else {
53 | server.setState(ServerStatusEnum.ONLINE.getCode());
54 | }
55 | //重启过
56 | if(StringUtils.isEmpty(server.getLastRebootTime()) ||!server.getLastRebootTime().equals(lastRestart)){
57 | log.info(">>>>服务器:{} 重启过, 开始启动中转", server.getServerName());
58 | List userForwardList = userPortForwardService.findServerEnabledForwardList(server.getId());
59 | for (UserPortForward userPortForward : userForwardList) {
60 | userPortForwardService.startForward(userPortForward, false);
61 | }
62 | server.setLastRebootTime(lastRestart);
63 | log.info(">>>>服务器:{} 重启过, 启动中转完成", server.getServerName());
64 | }
65 | serverService.save(server);
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/ForwardFlowRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.ForwardFlow;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserPort;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | public interface ForwardFlowRepository extends JpaRepository {
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/PortRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface PortRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/ServerRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.Server;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserServer;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | public interface ServerRepository extends JpaRepository {
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/SysConfigRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.SysConfig;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface SysConfigRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/UserPortForwardRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.UserPortForward;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface UserPortForwardRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/UserPortRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.Port;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserPort;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | public interface UserPortRepository extends JpaRepository {
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.User;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface UserRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/jpa/UserServerRepository.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.jpa;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.model.User;
4 | import com.leeroy.forwordpanel.forwordpanel.model.UserServer;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | public interface UserServerRepository extends JpaRepository {
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/Clash.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import java.util.Date;
10 |
11 | /**
12 | * clash配置
13 | */
14 | @Data
15 | public class Clash {
16 |
17 |
18 | @TableId(value = "id", type = IdType.ASSIGN_UUID)
19 | private String id;
20 |
21 | private String configName;
22 | private Integer userId;
23 | private Boolean disabled;
24 | private Boolean deleted;
25 | /**
26 | * 到期时间
27 | */
28 | @DateTimeFormat(pattern = "yyyy-MM-dd")
29 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
30 | private Date expireTime;
31 |
32 | private Date createTime;
33 |
34 | private Date updateTime;
35 | /**
36 | * 配置字符串
37 | */
38 | private String text;
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/ForwardFlow.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 |
7 | import javax.persistence.Entity;
8 | import javax.persistence.Id;
9 | import java.util.Date;
10 |
11 | /**
12 | * @program: forwordpanel
13 | * @description: 用户中转流量记录
14 | * @author: liruifeng
15 | * @created: 2020/09/17 14:06
16 | */
17 | @Entity
18 | @Data
19 | public class ForwardFlow {
20 |
21 | @Id
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 | //中转记录id
25 | private Integer forwardId;
26 | // 中转用户
27 | private Integer userId;
28 | //端口id
29 | private Integer portId;
30 | // 服务id
31 | private Integer serverId;
32 | // 目标ip
33 | private String remoteIp;
34 | // 目标主机地址
35 | private String remoteHost;
36 | // 流量使用量
37 | private Long dataUsage;
38 | // 目标主机端口
39 | private Integer remotePort;
40 | // 创建时间
41 | private Date createTime;
42 | //更新时间
43 | private Date updateTime;
44 | //删除表示
45 | private Boolean deleted;
46 | //禁用表示
47 | private Boolean disabled;
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/Port.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import javax.persistence.Entity;
10 | import javax.persistence.Id;
11 | import java.util.Date;
12 |
13 | /**
14 | * 端口信息
15 | */
16 | @Entity
17 | @Data
18 | public class Port {
19 |
20 | @Id
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 所属服务器
26 | */
27 | private Integer serverId;
28 |
29 | /**
30 | * 本地端口
31 | */
32 | private Integer localPort;
33 |
34 | /**
35 | * 外网端口
36 | */
37 | private Integer internetPort;
38 |
39 | private Date createTime;
40 |
41 | private Date updateTime;
42 |
43 | private Boolean deleted;
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/Resource.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import lombok.Data;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * 资源
9 | */
10 | @Data
11 | public class Resource {
12 |
13 | private Integer id;
14 |
15 | private String title;
16 |
17 | private String path;
18 |
19 | private boolean meta;
20 |
21 | private boolean hidden;
22 |
23 | private String icon;
24 |
25 | private List children;
26 |
27 | public Resource(Integer id, String title, String path, boolean meta, boolean hidden) {
28 | this.id = id;
29 | this.title = title;
30 | this.path = path;
31 | this.meta = meta;
32 | this.hidden = hidden;
33 | }
34 |
35 | public Resource(Integer id, String title, String path, String icon) {
36 | this.id = id;
37 | this.title = title;
38 | this.path = path;
39 | this.meta = true;
40 | this.hidden = false;
41 | this.icon = icon;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/Server.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import javax.persistence.Entity;
10 | import javax.persistence.Id;
11 | import java.util.Date;
12 |
13 | /**
14 | * 端口信息
15 | */
16 | @Entity
17 | @Data
18 | public class Server {
19 |
20 | @Id
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 |
25 | /**
26 | * 服务器所有者
27 | */
28 | private Integer ownerId;
29 |
30 | /**
31 | * 服务器名称
32 | */
33 | private String serverName;
34 |
35 | /**
36 | * 服务器host
37 | */
38 | private String host;
39 |
40 | /**
41 | * ssh端口
42 | */
43 | private Integer port;
44 |
45 | /**
46 | * 服务器 key
47 | */
48 | private String key;
49 |
50 | /**
51 | * 密码
52 | */
53 | private String username;
54 |
55 | /**
56 | * 用户名
57 | */
58 | private String password;
59 |
60 | /**
61 | * 服务器状态
62 | */
63 | private Integer state;
64 |
65 | private Date createTime;
66 |
67 | private Date updateTime;
68 |
69 | private Boolean deleted;
70 | /**
71 | * 最后一次重启时间
72 | */
73 | private String lastRebootTime;
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/SysConfig.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 |
7 | import javax.persistence.Entity;
8 | import javax.persistence.Id;
9 | import java.util.Date;
10 |
11 | /**
12 | * 系统配置
13 | */
14 | @Entity
15 | @Data
16 | public class SysConfig {
17 |
18 | @Id
19 | @TableId(value = "id", type = IdType.INPUT)
20 | private Integer id;
21 |
22 |
23 | /**
24 | * tg
25 | */
26 | private String telegram;
27 |
28 | /**
29 | * 邮箱
30 | */
31 | private String email;
32 |
33 | /**
34 | * 邮箱
35 | */
36 | private String qq;
37 |
38 | /**
39 | * 当前版本
40 | */
41 | private String version;
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/User.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import com.fasterxml.jackson.annotation.JsonFormat;
8 | import lombok.Data;
9 | import org.springframework.format.annotation.DateTimeFormat;
10 |
11 | import javax.persistence.Entity;
12 | import javax.persistence.Id;
13 | import javax.persistence.Table;
14 | import java.util.Date;
15 |
16 |
17 | @Table(name = "sys_user")
18 | @Entity
19 | @TableName("sys_user")
20 | @Data
21 | public class User {
22 | /**
23 | * ID
24 | */
25 | @Id
26 | @TableId(value = "id", type = IdType.AUTO)
27 | private Integer id;
28 |
29 | /**
30 | * 系统用户名称
31 | */
32 | @TableField("username")
33 | private String username;
34 |
35 | /**
36 | * 系统用户密码
37 | */
38 | private String password;
39 |
40 | /**
41 | * 手机号
42 | */
43 | private String userPhone;
44 |
45 | /**
46 | * 手机号
47 | */
48 | private String telegram;
49 |
50 |
51 | /**
52 | * 登记时间
53 | */
54 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
55 | private Date regTime;
56 |
57 | /**
58 | * 状态(0:无效;1:有效)
59 | */
60 | private Boolean disabled;
61 |
62 | /**
63 | * 删除表示
64 | */
65 | private Boolean deleted;
66 |
67 | /**
68 | * 用户流量限制
69 | */
70 | private Long dataLimit;
71 |
72 | /**
73 | * 流量使用量
74 | */
75 | private Long dataUsage;
76 |
77 | /**
78 | * 用户类型
79 | */
80 | private Integer userType;
81 |
82 | /**
83 | * 到期时间
84 | */
85 | private Date expireTime;
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/UserPort.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 |
4 | import com.baomidou.mybatisplus.annotation.IdType;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.fasterxml.jackson.annotation.JsonFormat;
7 | import lombok.Data;
8 | import org.springframework.format.annotation.DateTimeFormat;
9 |
10 | import javax.persistence.Entity;
11 | import javax.persistence.Id;
12 | import java.util.Date;
13 |
14 | /**
15 | * 端口
16 | */
17 | @Entity
18 | @Data
19 | public class UserPort {
20 |
21 | @Id
22 | @TableId(value = "id",type = IdType.AUTO)
23 | private Integer id;
24 | private Integer userId;
25 | private Integer portId;
26 | private Integer serverId;
27 | private Boolean disabled;
28 | private Boolean deleted;
29 | /**
30 | * 端口流量限制
31 | */
32 | private Long dataLimit;
33 | /**
34 | * 到期时间
35 | */
36 | @DateTimeFormat(pattern = "yyyy-MM-dd")
37 | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
38 | private Date expireTime;
39 |
40 | private Date createTime;
41 |
42 | private Date updateTime;
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/UserPortForward.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import lombok.Data;
7 | import org.springframework.format.annotation.DateTimeFormat;
8 |
9 | import javax.persistence.Entity;
10 | import javax.persistence.Id;
11 | import java.util.Date;
12 |
13 | /**
14 | * 端口转发实体
15 | */
16 | @Entity
17 | @Data
18 | public class UserPortForward {
19 |
20 | @Id
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 | // 中转用户
24 | private Integer userId;
25 | //端口id
26 | private Integer portId;
27 | // 服务id
28 | private Integer serverId;
29 | // 目标ip
30 | private String remoteIp;
31 | // 目标主机地址
32 | private String remoteHost;
33 | // 流量使用量
34 | private Long dataUsage;
35 | // 目标主机端口
36 | private Integer remotePort;
37 | // 创建时间
38 | private Date createTime;
39 | //更新时间
40 | private Date updateTime;
41 | //删除表示
42 | private Boolean deleted;
43 | //禁用表示
44 | private Boolean disabled;
45 |
46 | private Integer state;
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/UserServer.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 |
7 | import javax.persistence.Entity;
8 | import javax.persistence.Id;
9 |
10 | @Entity
11 | @Data
12 | public class UserServer {
13 |
14 | @Id
15 | @TableId(value = "id",type = IdType.AUTO)
16 | private Integer id;
17 | /**
18 | * 用户id
19 | */
20 | private Integer userId;
21 | /**
22 | * 服务器id
23 | */
24 | private Integer serverId;
25 |
26 | private Boolean deleted;
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/model/UserToken.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.model;
2 |
3 | import lombok.Data;
4 | import lombok.NoArgsConstructor;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * 用户token
10 | */
11 | @Data
12 | @NoArgsConstructor
13 | public class UserToken implements Serializable {
14 |
15 |
16 | /**
17 | * 用户token
18 | */
19 | private String token;
20 |
21 | /**
22 | * 用户名
23 | */
24 | private String username;
25 |
26 | /**
27 | * 用户id
28 | */
29 | private Integer userId;
30 |
31 | /**
32 | * 超时时间
33 | */
34 | private Long expireTime;
35 |
36 | /**
37 | * 创建时间
38 | */
39 | private Long createTime;
40 |
41 | /**
42 | * 更新时间
43 | */
44 | private Long updateTime;
45 |
46 | public static UserToken getInstance(String token, String username, Integer userId) {
47 | UserToken userToken = new UserToken();
48 | userToken.setUsername(username);
49 | userToken.setUserId(userId);
50 | userToken.setToken(token);
51 | userToken.setExpireTime(System.currentTimeMillis()+1000*60*30);
52 | return userToken;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/service/ConfigService.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.service;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
6 | import com.baomidou.mybatisplus.core.toolkit.Wrappers;
7 | import com.github.pagehelper.Page;
8 | import com.github.pagehelper.PageHelper;
9 | import com.github.pagehelper.PageInfo;
10 | import com.leeroy.forwordpanel.forwordpanel.common.WebCurrentData;
11 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
12 | import com.leeroy.forwordpanel.forwordpanel.dao.ClashDao;
13 | import com.leeroy.forwordpanel.forwordpanel.dto.PageRequest;
14 | import com.leeroy.forwordpanel.forwordpanel.model.Clash;
15 | import org.springframework.beans.BeanUtils;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.stereotype.Service;
18 | import org.springframework.util.StringUtils;
19 | import org.yaml.snakeyaml.DumperOptions;
20 | import org.yaml.snakeyaml.Yaml;
21 |
22 | import java.io.StringWriter;
23 | import java.util.ArrayList;
24 | import java.util.Date;
25 | import java.util.Iterator;
26 | import java.util.List;
27 |
28 | @Service
29 | public class ConfigService {
30 |
31 | @Autowired
32 | private ClashDao clashDao;
33 |
34 |
35 | /**
36 | * 保存clash
37 | */
38 | public ApiResponse save(Clash clash) {
39 | clash.setUserId(WebCurrentData.getUserId());
40 | if (StringUtils.isEmpty(clash.getId())) {
41 | clash.setDeleted(false);
42 | clash.setDisabled(false);
43 | clash.setCreateTime(new Date());
44 | clashDao.insert(clash);
45 | } else {
46 | Clash existClash = clashDao.selectById(clash.getId());
47 | BeanUtils.copyProperties(clash, existClash);
48 | existClash.setUpdateTime(new Date());
49 | clashDao.updateById(existClash);
50 | }
51 | return ApiResponse.ok();
52 | }
53 |
54 | public ApiResponse getNodeList(String id){
55 | Clash clash = clashDao.selectById(id);
56 | Yaml yaml = new Yaml();
57 | JSONObject jsonObject = yaml.loadAs(clash.getText(), JSONObject.class);
58 | JSONArray proxies = jsonObject.getJSONArray("proxies");
59 | return ApiResponse.ok(proxies);
60 | }
61 |
62 | /**
63 | * 保存节点列表
64 | * @param nodeList
65 | * @param id
66 | * @return
67 | */
68 | public ApiResponse saveNodeList(JSONArray nodeList, String id){
69 | Clash clash = clashDao.selectById(id);
70 | DumperOptions dumperOptions = new DumperOptions();
71 |
72 | dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
73 | dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
74 | Yaml yaml = new Yaml(dumperOptions);
75 | JSONObject jsonObject = yaml.loadAs(clash.getText(), JSONObject.class);
76 | parseProxies(nodeList);
77 | jsonObject.put("proxies", nodeList);
78 | List groupProxies = new ArrayList<>();
79 | for (int i = 0; i < nodeList.size(); i++) {
80 | JSONObject item = nodeList.getJSONObject(i);
81 | groupProxies.add(item.getString("name"));
82 | }
83 | JSONArray proxyGroups = jsonObject.getJSONArray("proxy-groups");
84 | for (int i = 0; i < proxyGroups.size(); i++) {
85 | JSONObject item = proxyGroups.getJSONObject(i);
86 | JSONArray proxies = item.getJSONArray("proxies");
87 | Iterator iterator = proxies.iterator();
88 | while (iterator.hasNext()) {
89 | String name = (String) iterator.next();
90 | if(name.indexOf("DIRECT")>=0){
91 | continue;
92 | }
93 | //排除分组j
94 | if (isGroup(proxyGroups, name)){
95 | continue;
96 | }
97 |
98 | iterator.remove();
99 | }
100 | proxies.addAll(groupProxies);
101 | item.put("proxies", proxies);
102 | }
103 | StringWriter writer = new StringWriter();
104 | yaml.dump(jsonObject, writer);
105 | clash.setText(writer.toString());
106 | clashDao.updateById(clash);
107 | return ApiResponse.ok();
108 | }
109 |
110 | private void parseProxies(JSONArray nodeList){
111 | for (int i = 0; i < nodeList.size(); i++) {
112 | JSONObject item = nodeList.getJSONObject(i);
113 | item.put("name", item.getString("name"));
114 | item.put("server", item.getString("server"));
115 | item.put("port", item.getInteger("port"));
116 | item.put("password", item.getString("password"));
117 | item.put("sni", item.getString("sni"));
118 | item.put("type", item.getString("type"));
119 | }
120 | }
121 |
122 | private boolean isGroup(JSONArray proxyGroups, String name){
123 | //排除分组j
124 | for (int j = 0; j < proxyGroups.size(); j++) {
125 | JSONObject proxy = proxyGroups.getJSONObject(j);
126 | if( proxy.getString("name").equals(name)){
127 | return true;
128 | }
129 | }
130 | return false;
131 | }
132 |
133 | /**
134 | * 查询clash列表
135 | *
136 | * @return
137 | */
138 | public PageInfo findClashList(PageRequest pageRequest) {
139 | Integer userId = WebCurrentData.getUserId();
140 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(Clash::getUserId, userId).eq(Clash::getDeleted, false);
141 | Page page = PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize());
142 | List clashList = clashDao.selectList(queryWrapper);
143 | PageInfo pageInfo = page.toPageInfo();
144 | pageInfo.setList(clashList);
145 | return pageInfo;
146 | }
147 |
148 | /**
149 | * 删除clash
150 | */
151 | public void delClash(String id) {
152 | Clash userPort = new Clash();
153 | userPort.setId(id);
154 | userPort.setDeleted(true);
155 | clashDao.updateById(userPort);
156 | }
157 |
158 | /**
159 | * 查询clash
160 | * @param id
161 | * @return
162 | */
163 | public Clash findClashById(String id){
164 | return clashDao.selectById(id);
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/service/ForwardService.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.service;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.leeroy.forwordpanel.forwordpanel.common.util.IpUtil;
5 | import com.leeroy.forwordpanel.forwordpanel.common.util.ShellUtil;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.DataFlow;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.stereotype.Service;
9 | import org.springframework.util.StringUtils;
10 |
11 | import java.math.BigDecimal;
12 |
13 | @Slf4j
14 | @Service
15 | public class ForwardService {
16 |
17 | /**
18 | * 添加转发
19 | *
20 | * @param remoteHost
21 | * @param remotePort
22 | * @param localPort
23 | */
24 | public void addForward(String remoteHost, Integer remotePort, Integer localPort) {
25 | stopForward(remoteHost, remotePort, localPort);
26 | String localIp = IpUtil.getLocalIpByNetcard();
27 | ShellUtil.execShell(String.format("iptables -t nat -A PREROUTING -p tcp --dport %d -j DNAT --to-destination %s:%d", localPort, remoteHost, remotePort));
28 | ShellUtil.execShell(String.format("iptables -t nat -A PREROUTING -p udp --dport %d -j DNAT --to-destination %s:%d", localPort, remoteHost, remotePort));
29 | ShellUtil.execShell(String.format("iptables -t nat -A POSTROUTING -p tcp -d %s --dport %d -j SNAT --to-source %s", remoteHost, remotePort, localIp));
30 | ShellUtil.execShell(String.format("iptables -t nat -A POSTROUTING -p udp -d %s --dport %d -j SNAT --to-source %s", remoteHost, remotePort, localIp));
31 | String flow = ShellUtil.execShell(String.format("iptables -n -v -L -t filter -x | grep %s | awk '{print $2}'", remoteHost));
32 | log.info("fow: {}", flow);
33 | if (StringUtils.isEmpty(flow)) {
34 | ShellUtil.execShell(String.format("iptables -I FORWARD -s %s", remoteHost));
35 | }
36 | }
37 |
38 |
39 | /**
40 | * 获取转发流量
41 | * @param remoteHost
42 | * @param remotePort
43 | * @return
44 | */
45 | public String getPortFlow(String remoteHost, Integer remotePort) {
46 | String result = ShellUtil.execShell(String.format("iptables -n -v -L -t filter -x | grep %s | awk '{print $2}'", remoteHost));
47 | result = result.replaceAll("\n", "");
48 | log.info("flow:{}", result);
49 | return StringUtils.isEmpty(result)?"0":result;
50 | }
51 |
52 |
53 | /**
54 | * 重置流量
55 | * @param remoteHost
56 | * @param remotePort
57 | */
58 | public void resetFlowCount(String remoteHost, Integer remotePort){
59 | ShellUtil.execShell(String.format("iptables -D FORWARD -s %s", remoteHost));
60 | ShellUtil.execShell(String.format("iptables -I FORWARD -s %s", remoteHost));
61 | }
62 |
63 | /**
64 | * 重置流量
65 | * @param remoteHost
66 | * @param remotePort
67 | */
68 | public void deleteFlowCount(String remoteHost, Integer remotePort){
69 | ShellUtil.execShell(String.format("iptables -D FORWARD -p tcp --dport %s -d %s", remotePort, remoteHost));
70 | ShellUtil.execShell(String.format("iptables -D FORWARD -p udp --dport %s -d %s", remotePort, remoteHost));
71 | }
72 |
73 |
74 | /**
75 | * 停止转发
76 | *
77 | * @param remoteHost
78 | * @param remotePort
79 | * @param localPort
80 | */
81 | public void stopForward(String remoteHost, Integer remotePort, Integer localPort) {
82 | String dnatStr = ShellUtil.execShell(String.format("iptables -L PREROUTING -n -t nat --line-number |grep DNAT|grep \"dpt:%d \"|sort -r|awk '{print $1,$3,$9}'|tr \" \" \":\"|tr \"\\n\" \" \"", localPort));
83 | log.info(dnatStr);
84 | dnatStr.trim();
85 | if(StringUtils.isEmpty(dnatStr)){
86 | return;
87 | }
88 | String[] dnatList = dnatStr.split(" ");
89 | log.info(JSON.toJSONString(dnatList));
90 | for (String item : dnatList) {
91 | item = item.trim();
92 | if(StringUtils.isEmpty(item)){
93 | continue;
94 | }
95 | String[] itemList = item.split(":");
96 | log.info(JSON.toJSONString(itemList));
97 | ShellUtil.execShell(String.format("iptables -t nat -D PREROUTING %s", itemList[0]));
98 | String snatStr = ShellUtil.execShell(String.format("iptables -L POSTROUTING -n -t nat --line-number|grep SNAT|grep %s|grep dpt:%s|grep %s|awk '{print $1}'|sort -r|tr \"\\n\" \" \"", itemList[3], itemList[4], itemList[1]));
99 | if(StringUtils.isEmpty(snatStr)){
100 | continue;
101 | }
102 | snatStr = snatStr.trim();
103 | if(StringUtils.isEmpty(snatStr)){
104 | continue;
105 | }
106 | String[] snatList = snatStr.split(" ");
107 | log.info(JSON.toJSONString(snatList));
108 | for (String s : snatList) {
109 | if(StringUtils.isEmpty(s)){
110 | continue;
111 | }
112 | ShellUtil.execShell("iptables -t nat -D POSTROUTING "+ s);
113 | }
114 | }
115 |
116 | }
117 |
118 | private String getForwardKey(String remoteHost, Integer remotePort, Integer localPort) {
119 | return remoteHost + remotePort + localPort;
120 | }
121 |
122 |
123 | public static void main(String[] args) {
124 | String a = " ";
125 | System.out.println();
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/service/LoginService.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.service;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
4 | import com.leeroy.forwordpanel.forwordpanel.common.util.DigestUtils;
5 | import com.leeroy.forwordpanel.forwordpanel.common.util.TokenUtil;
6 | import com.leeroy.forwordpanel.forwordpanel.dto.LoginDTO;
7 | import com.leeroy.forwordpanel.forwordpanel.model.User;
8 | import com.leeroy.forwordpanel.forwordpanel.model.UserToken;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Service;
11 | import org.springframework.util.StringUtils;
12 |
13 | import javax.servlet.http.HttpServletRequest;
14 |
15 | @Service
16 | public class LoginService {
17 |
18 | @Autowired
19 | private UserService userService;
20 |
21 | @Autowired
22 | private UserTokenService userTokenService;
23 |
24 | /**
25 | * 登录
26 | *
27 | * @param loginDTO
28 | * @return
29 | */
30 | public ApiResponse login(LoginDTO loginDTO) {
31 | if (StringUtils.isEmpty(loginDTO.getUsername()) || StringUtils.isEmpty(loginDTO.getPassword())) {
32 | return ApiResponse.error("400", "用户名密码不能为空");
33 | }
34 | User baseAdminUser = userService.findByUserName(loginDTO.getUsername());
35 | if (baseAdminUser == null) {
36 | return ApiResponse.error("403", "用户名密码错误");
37 | }
38 | if (!DigestUtils.Md5(loginDTO.getUsername(), loginDTO.getPassword()).equals(baseAdminUser.getPassword())) {
39 | return ApiResponse.error("403", "用户名密码错误");
40 | }
41 | String token = TokenUtil.makeToken(baseAdminUser.getUsername(), baseAdminUser.getPassword());
42 | UserToken userToken = UserToken.getInstance(token, baseAdminUser.getUsername(), baseAdminUser.getId());
43 | userTokenService.saveUserToken(userToken);
44 | return ApiResponse.ok(userToken);
45 | }
46 |
47 | public ApiResponse authToken(String token){
48 | return ApiResponse.ok(userTokenService.getUserByToken(token));
49 | }
50 |
51 | /**
52 | * 登出
53 | *
54 | * @return
55 | */
56 | public void logout(HttpServletRequest request) {
57 | String token = TokenUtil.getToken(request);
58 | userTokenService.delToken(token);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/service/SysConfigService.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.service;
2 |
3 | import com.leeroy.forwordpanel.forwordpanel.common.response.ApiResponse;
4 | import com.leeroy.forwordpanel.forwordpanel.dao.SysConfigDao;
5 | import com.leeroy.forwordpanel.forwordpanel.model.SysConfig;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.beans.factory.annotation.Value;
9 | import org.springframework.stereotype.Service;
10 |
11 | /**
12 | * @Title: 系统配置
13 | * @Description:
14 | * @author: leeroy
15 | * @version: 1.0
16 | * @date: 2020/11/21 11:04
17 | */
18 | @Slf4j
19 | @Service
20 | public class SysConfigService {
21 |
22 | @Autowired
23 | SysConfigDao sysConfigDao;
24 |
25 | @Value("${panel.version:test}")
26 | private String version;
27 |
28 | /**
29 | * 保存clash
30 | */
31 | public ApiResponse save(SysConfig config) {
32 | if (config.getId() != null) {
33 | sysConfigDao.updateById(config);
34 | } else {
35 | config.setId(1);
36 | sysConfigDao.insert(config);
37 | }
38 | return ApiResponse.ok();
39 | }
40 |
41 | /**
42 | * 获取配置
43 | *
44 | * @return
45 | */
46 | public ApiResponse getConfig() {
47 | SysConfig sysConfig = sysConfigDao.selectById(1);
48 |
49 | if (sysConfig == null) {
50 | sysConfig = new SysConfig();
51 | sysConfig.setVersion(version);
52 | sysConfig.setId(1);
53 | sysConfig.setTelegram("");
54 | sysConfigDao.insert(sysConfig);
55 | } else {
56 | sysConfig.setVersion(version);
57 | }
58 | return ApiResponse.ok(sysConfig);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/leeroy/forwordpanel/forwordpanel/service/UserTokenService.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel.service;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers;
5 | import com.leeroy.forwordpanel.forwordpanel.dao.UserDao;
6 | import com.leeroy.forwordpanel.forwordpanel.dao.UserTokenDao;
7 | import com.leeroy.forwordpanel.forwordpanel.model.User;
8 | import com.leeroy.forwordpanel.forwordpanel.model.UserToken;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Service;
11 |
12 | /**
13 | * 用户token
14 | */
15 | @Service
16 | public class UserTokenService {
17 |
18 | @Autowired
19 | private UserTokenDao userTokenDao;
20 |
21 | @Autowired
22 | private UserDao userDao;
23 |
24 | /**
25 | * 保存用户token
26 | * @param userToken
27 | */
28 | public void saveUserToken(UserToken userToken){
29 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(UserToken::getToken, userToken)
30 | .gt(UserToken::getExpireTime, System.currentTimeMillis());
31 | UserToken existToken = userTokenDao.selectOne(queryWrapper);
32 | if(existToken!=null){
33 | existToken.setUpdateTime(System.currentTimeMillis());
34 | existToken.setExpireTime(existToken.getExpireTime()+30*60*1000);
35 | userTokenDao.updateById(userToken);
36 | }else {
37 | userToken.setCreateTime(System.currentTimeMillis());
38 | userTokenDao.insert(userToken);
39 | }
40 | }
41 |
42 | public void updateUserToken(UserToken userToken){
43 | userTokenDao.update(userToken, Wrappers.lambdaQuery().eq(UserToken::getUserId, userToken.getUserId()).eq(UserToken::getToken, userToken.getToken()));
44 | }
45 |
46 |
47 | /**
48 | * 获取用户token
49 | * @param token
50 | * @return
51 | */
52 | public UserToken getUserToken(String token){
53 | if(token==null){
54 | return null;
55 | }
56 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(UserToken::getToken, token)
57 | .gt(UserToken::getExpireTime, System.currentTimeMillis());
58 | return userTokenDao.selectOne(queryWrapper);
59 | }
60 |
61 | /**
62 | * 获取用户token
63 | * @param token
64 | * @return
65 | */
66 | public User getUserByToken(String token){
67 | if(token==null){
68 | return null;
69 | }
70 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(UserToken::getToken, token)
71 | .gt(UserToken::getExpireTime, System.currentTimeMillis());
72 | UserToken userToken = userTokenDao.selectOne(queryWrapper);
73 | if(userToken==null){
74 | return null;
75 | }
76 | return userDao.selectById(userToken.getUserId());
77 | }
78 |
79 | /**
80 | * 删除token
81 | */
82 | public void delToken(String token){
83 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(UserToken::getToken, token);
84 | userTokenDao.delete(queryWrapper);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #���þ�̬��Դ·��������Զ��ŷָ�
2 | server.port=8080
3 | spring.resources.static-locations= classpath:static/,file:static/
4 | spring.datasource.url=jdbc:h2:./forward_db;DB_CLOSE_ON_EXIT=FALSE
5 | spring.datasource.driverClassName=org.h2.Driver
6 | spring.datasource.username=sa
7 | spring.datasource.password=*yBHJHud$f45fgf
8 | # H2
9 | spring.h2.console.enabled=true
10 | spring.h2.console.path=/h2
11 | spring.h2.console.settings.web-allow-others=true
12 | spring.jpa.generate-ddl=false
13 | spring.jpa.show-sql=true
14 | spring.jpa.hibernate.ddl-auto=update
15 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
16 | panel.version=test
17 | spring.servlet.multipart.max-file-size=1024MB
18 | spring.servlet.multipart.max-request-size=1024MB
19 |
20 | #mybatis-plus配置控制台打印完整带参数SQL语句
21 | #mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
22 | #mybatis-plus.configuration.map-underscore-to-camel-case=true
23 | panel.default-password=XDZZ@123
24 | ssh.privateKeyPath=D:\\id_rsa_old
25 |
--------------------------------------------------------------------------------
/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE sys_user (
2 | id int NOT NULL AUTO_INCREMENT ,
3 | username varchar(50) NOT NULL,
4 | password varchar(250) DEFAULT NULL ,
5 | user_phone varchar(11) ,
6 | telegram varchar(11) ,
7 | reg_time DATE ,
8 | data_limit BIGINT,
9 | expire_time DATE,
10 | data_usage BIGINT,
11 | user_type INTEGER NOT NULL DEFAULT 1,
12 | disabled BOOLEAN ,
13 | deleted BOOLEAN
14 | );
15 |
16 | INSERT INTO sys_user VALUES (1, 'admin', '028974a1894e75000bf41636adc8ed81', '11111111111','leeroy','2020-01-03', 107374182400,null,null, 0, false, false);
17 |
18 | CREATE TABLE user_port (
19 | id int NOT NULL AUTO_INCREMENT ,
20 | local_port int NOT NULL,
21 | user_id int NOT NULL ,
22 | port_id int NOT NULL ,
23 | data_limit BIGINT,
24 | data_usage BIGINT,
25 | disabled BOOLEAN ,
26 | deleted BOOLEAN ,
27 | expire_time DATE,
28 | create_time TIMESTAMP ,
29 | update_time TIMESTAMP
30 | );
31 |
32 |
33 | CREATE TABLE user_token (
34 | id int NOT NULL AUTO_INCREMENT ,
35 | token varchar(250) NOT NULL,
36 | username varchar(50) NOT NULL,
37 | user_id INTEGER ,
38 | create_time BIGINT ,
39 | update_time BIGINT,
40 | expire_time BIGINT
41 | );
42 |
43 | CREATE TABLE user_port_forward (
44 | id int NOT NULL AUTO_INCREMENT ,
45 | user_id int NOT NULL ,
46 | local_port int NOT NULL,
47 | remote_ip varchar(64),
48 | remote_host varchar(64),
49 | remote_port int,
50 | data_limit BIGINT,
51 | data_usage BIGINT,
52 | disabled BOOLEAN ,
53 | deleted BOOLEAN ,
54 | create_time TIMESTAMP ,
55 | update_time TIMESTAMP
56 | );
57 |
58 | CREATE TABLE clash (
59 | id varchar(50) NOT NULL,
60 | config_name varchar(50) NOT NULL,
61 | text CLOB NOT NULL,
62 | user_id int NOT NULL ,
63 | disabled BOOLEAN ,
64 | deleted BOOLEAN ,
65 | expire_time DATE,
66 | create_time TIMESTAMP ,
67 | update_time TIMESTAMP
68 | );
69 |
70 | CREATE TABLE port (
71 | id int NOT NULL AUTO_INCREMENT,
72 | local_port int NOT NULL ,
73 | internet_port int NOT NULL ,
74 | deleted BOOLEAN,
75 | create_time TIMESTAMP,
76 | update_time TIMESTAMP
77 | );
78 |
79 | CREATE TABLE server(
80 | id int NOT NULL AUTO_INCREMENT,
81 | server_name varchar(128) NOT NULL ,
82 | host varchar(256) NOT NULL ,
83 | port int NOT NULL ,
84 | state int NOT NULL DEFAULT 1 ,
85 | deleted BOOLEAN,
86 | create_time TIMESTAMP,
87 | update_time TIMESTAMP
88 | );
89 |
90 |
91 | alter table server add column key varchar(256) NOT NULL ;
92 |
93 |
94 | -- 07-22 local_port不再存储
95 | alter table user_port drop local_port;
96 | alter table user_port drop port_id;
97 | alter table user_port add local_port int default NULL;
98 | alter table user_port add port_id int default NULL;
99 |
100 | alter table user_port_forward drop local_port;
101 | alter table user_port_forward add local_port int default NULL;
102 | alter table user_port_forward add port_id int NOT NULL;
103 |
104 | -- 07-28 增加user_server
105 | CREATE TABLE user_server(
106 | id int NOT NULL AUTO_INCREMENT,
107 | user_id int NOT NULL ,
108 | server_id int NOT NULL DEFAULT 1 ,
109 | deleted BOOLEAN,
110 | create_time TIMESTAMP,
111 | update_time TIMESTAMP
112 | );
113 | alter table server add column owner_id int;
114 | alter table port add column server_id int;
115 | alter table user_port add server_id int default NULL;
116 | alter table user_port_forward add server_id int default NULL;
117 |
118 | alter table server add column username varchar(128);
119 | alter table server add column password varchar(128);
120 |
121 | CREATE TABLE forward_flow (
122 | id int NOT NULL AUTO_INCREMENT ,
123 | forward_id int not NULL,
124 | user_id int NOT NULL ,
125 | local_port int default NULL,
126 | remote_ip varchar(64),
127 | remote_host varchar(64),
128 | port_id int NOT NULL,
129 | remote_port int,
130 | data_limit BIGINT,
131 | data_usage BIGINT,
132 | disabled BOOLEAN ,
133 | deleted BOOLEAN ,
134 | server_id int default NULL,
135 | create_time TIMESTAMP ,
136 | update_time TIMESTAMP
137 | );
138 |
--------------------------------------------------------------------------------
/src/main/resources/scripts/turnOnNat.sh:
--------------------------------------------------------------------------------
1 | sed -n '/^net.ipv4.ip_forward=1/'p /etc/sysctl.conf | grep -q "net.ipv4.ip_forward=1";if [ $? -ne 0 ]; then echo -e "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p;fi
2 | arr1=(`iptables -L FORWARD -n --line-number |grep "REJECT"|grep "0.0.0.0/0"|sort -r|awk '{print $1,$2,$5}'|tr " " ":"|tr "\n" " "`);for cell in ${arr1[@]};do arr2=(`echo $cell|tr ":" " "`);index=${arr2[0]};echo 删除禁止FOWARD的规则$index;iptables -D FORWARD $index;done
3 | iptables --policy FORWARD ACCEPT
4 |
--------------------------------------------------------------------------------
/src/main/resources/static/avatar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/avatar.gif
--------------------------------------------------------------------------------
/src/main/resources/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/favicon.ico
--------------------------------------------------------------------------------
/src/main/resources/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/favicon.png
--------------------------------------------------------------------------------
/src/main/resources/static/index.html:
--------------------------------------------------------------------------------
1 | 闲蛋中转
--------------------------------------------------------------------------------
/src/main/resources/static/reward.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/reward.gif
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-22fe9ae1.d62c05ee.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-258281f4]{margin:30px}.dashboard-text[data-v-258281f4]{font-size:30px;line-height:46px}.drawer-body[data-v-258281f4]{padding:20px}.demo-drawer__footer[data-v-258281f4]{padding-top:20px}.edit-cell[data-v-258281f4]{min-height:35px;cursor:pointer}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-2d423526.e6231e8e.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-dac09a84]{margin:30px}.dashboard-text[data-v-dac09a84]{font-size:30px;line-height:46px}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-480b22f6.a41dcdae.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-009db799]{margin:30px}.dashboard-text[data-v-009db799]{font-size:30px;line-height:46px}.drawer-body[data-v-009db799]{padding:20px}.demo-drawer__footer[data-v-009db799]{padding-top:20px}.edit-cell[data-v-009db799]{min-height:35px;cursor:pointer}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-4c26ca85.31d18062.css:
--------------------------------------------------------------------------------
1 | .el-drawer.rtl{overflow:scroll}.dashboard-container[data-v-2b255493]{margin:30px}.dashboard-text[data-v-2b255493]{font-size:30px;line-height:46px}.top-pannel[data-v-2b255493]{margin:10px 0 10px 0;color:#909399}.top-span[data-v-2b255493]{margin-right:20px;line-height:30px}.top-span.mobile[data-v-2b255493]{display:block}.top-text[data-v-2b255493]{color:#606266}.drawer-body[data-v-2b255493]{padding:20px}.item-box .server-status[data-v-2b255493]{position:absolute;right:15px;top:5px;font-size:12px}.item-box .server-status.online[data-v-2b255493]{color:#adff2f}.item-box .server-status.outline[data-v-2b255493]{color:red}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-632b8606.9ca93816.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-58607407]{margin:30px}.dashboard-text[data-v-58607407]{font-size:30px;line-height:46px}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-76cac56b.fcf8ba06.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-7fb10969]{margin:30px}.dashboard-text[data-v-7fb10969]{font-size:30px;line-height:46px}.drawer-body[data-v-7fb10969]{padding:20px}.demo-drawer__footer[data-v-7fb10969]{padding-top:20px}.state-normal[data-v-7fb10969]{font-size:12px}.state-fail[data-v-7fb10969]{color:#f56c6c;font-size:12px}.state-online[data-v-7fb10969]{color:#67c23a;font-size:12px}.item-box[data-v-7fb10969]{position:relative}.item-box .server-status[data-v-7fb10969]{position:absolute;right:15px;top:5px}.item-box .server-status.online[data-v-7fb10969]{color:#adff2f}.item-box .server-status.outline[data-v-7fb10969]{color:red}.item-box .port-manage[data-v-7fb10969]{line-height:30px;padding:0 5px;float:right;font-size:12px}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-76cea4de.3c7f5ad9.css:
--------------------------------------------------------------------------------
1 | .wscn-http404-container[data-v-c095f994]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-c095f994]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-c095f994]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-c095f994]{width:100%}.wscn-http404 .pic-404__child[data-v-c095f994]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-c095f994]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-c095f994;animation-name:cloudLeft-data-v-c095f994;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-c095f994]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-c095f994;animation-name:cloudMid-data-v-c095f994;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-c095f994]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-c095f994;animation-name:cloudRight-data-v-c095f994;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-c095f994{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-c095f994{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-c095f994{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-c095f994{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-c095f994{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-c095f994{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-c095f994]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-c095f994]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-c095f994],.wscn-http404 .bullshit__oops[data-v-c095f994]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-c095f994;animation-name:slideUp-data-v-c095f994;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-c095f994]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-c095f994]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-c095f994],.wscn-http404 .bullshit__return-home[data-v-c095f994]{opacity:0;-webkit-animation-name:slideUp-data-v-c095f994;animation-name:slideUp-data-v-c095f994;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-c095f994]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-c095f994{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-c095f994{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-9fdcb8cc.e86064da.css:
--------------------------------------------------------------------------------
1 | @supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-69a56f99]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-69a56f99]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-69a56f99]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-69a56f99]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-69a56f99]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-69a56f99]{position:relative}.login-container .title-container .title[data-v-69a56f99]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-69a56f99]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-a2c7894a.dc547638.css:
--------------------------------------------------------------------------------
1 | .el-drawer.rtl{overflow:scroll}.dashboard-container[data-v-1d9ca9eb]{margin:30px}.dashboard-text[data-v-1d9ca9eb]{font-size:30px;line-height:46px}.drawer-body[data-v-1d9ca9eb]{padding:20px}.drawer-body .drawer-select[data-v-1d9ca9eb]{margin:auto;margin-left:20px}.drawer-body .drawer-select.mobile[data-v-1d9ca9eb]{width:98%;margin:10px auto 0;display:block}.demo-drawer__footer[data-v-1d9ca9eb]{padding-top:20px}.el-drawer__body[data-v-1d9ca9eb]{overflow:auto}.reset[data-v-1d9ca9eb]{line-height:30px;padding:0 10px;float:right;font-size:12px}.item-box .server-status[data-v-1d9ca9eb]{position:absolute;right:15px;top:5px;font-size:12px}.item-box .server-status.online[data-v-1d9ca9eb]{color:#adff2f}.item-box .server-status.outline[data-v-1d9ca9eb]{color:red}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-e732e32c.1a2a53c6.css:
--------------------------------------------------------------------------------
1 | .dashboard-container[data-v-70b61e79]{margin:30px}.dashboard-text[data-v-70b61e79]{font-size:30px;line-height:46px}
--------------------------------------------------------------------------------
/src/main/resources/static/static/css/chunk-libs.3dfb7769.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
--------------------------------------------------------------------------------
/src/main/resources/static/static/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/static/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/src/main/resources/static/static/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/static/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/src/main/resources/static/static/img/404.a57b6f31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/static/img/404.a57b6f31.png
--------------------------------------------------------------------------------
/src/main/resources/static/static/img/404_cloud.0f4bc32b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/static/img/404_cloud.0f4bc32b.png
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-2d423526.31af6728.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d423526"],{4731:function(t,e,r){"use strict";r.d(e,"e",(function(){return n})),r.d(e,"f",(function(){return o})),r.d(e,"d",(function(){return i})),r.d(e,"h",(function(){return s})),r.d(e,"a",(function(){return l})),r.d(e,"b",(function(){return d}));var a=r("b775");function n(t){return Object(a["a"])({url:"/port/getPage",method:"post",data:t})}function o(t){return Object(a["a"])({url:"/port/getPortList",method:"post",data:t})}function i(t){return Object(a["a"])({url:"/port/delete",method:"get",params:t})}function s(t){return Object(a["a"])({url:"/port/save",method:"post",data:t})}function l(t){return Object(a["a"])({url:"/port/batchDelete",method:"post",data:t})}function d(t){return Object(a["a"])({url:"/port/batchSave",method:"post",data:t})}},4942:function(t,e,r){"use strict";var a=r("ced1"),n=r.n(a);n.a},aa22:function(t,e,r){"use strict";r.d(e,"d",(function(){return n})),r.d(e,"c",(function(){return o})),r.d(e,"b",(function(){return i})),r.d(e,"a",(function(){return s})),r.d(e,"e",(function(){return l}));var a=r("b775");function n(t){return Object(a["a"])({url:"/server/getPage",method:"post",data:t})}function o(t){return Object(a["a"])({url:"/server/getList",method:"get",data:t})}function i(t){return Object(a["a"])({url:"/server/getForwardServerList",method:"get",params:t})}function s(t){return Object(a["a"])({url:"/server/delete",method:"get",params:t})}function l(t){return Object(a["a"])({url:"/server/save",method:"post",data:t})}},b2dd:function(t,e,r){"use strict";r.r(e);var a=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"app-container"},[r("div",{staticClass:"searchBody"},[r("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchForm},nativeOn:{submit:function(t){t.preventDefault()}}},[r("el-form-item",[r("el-button",{attrs:{type:"success",size:"mini",icon:"el-icon-plus"},on:{click:t.showAddDialog}},[t._v("添加端口")])],1)],1)],1),r("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,"row-key":"id",border:"","tree-props":{children:"children",hasChildren:"hasChildren"}}},[r("el-table-column",{attrs:{label:"行号",type:"index",width:"50"}}),r("el-table-column",{attrs:{label:"本地端口",prop:"localPort"}}),r("el-table-column",{attrs:{label:"外网端口",prop:"internetPort"}}),r("el-table-column",{attrs:{label:"所属服务器",prop:"serverName"}}),r("el-table-column",{attrs:{label:"服务器IP",prop:"serverHost"}}),r("el-table-column",{attrs:{label:"创建时间",width:"160"},scopedSlots:t._u([{key:"default",fn:function(e){return[r("span",[t._v(t._s(t._f("parseTime")(e.row.createTime,"{y}-{m}-{d} {h}:{i}:{s}")))])]}}])}),r("el-table-column",{attrs:{label:"修改时间",width:"160"},scopedSlots:t._u([{key:"default",fn:function(e){return[r("span",[t._v(t._s(t._f("parseTime")(e.row.updateTime,"{y}-{m}-{d} {h}:{i}:{s}")))])]}}])}),r("el-table-column",{attrs:{label:"操作",fixed:"right",width:"250"},scopedSlots:t._u([{key:"default",fn:function(e){return[r("el-button",{attrs:{type:"primary",size:"mini",title:"编辑"},on:{click:function(r){return t.showEditDialog(e.row)}}},[t._v("编辑")]),r("el-button",{attrs:{type:"primary",size:"mini",title:"复制"},on:{click:function(r){return t.copyRow(e.row)}}},[t._v("复制")]),r("el-button",{attrs:{type:"danger",size:"mini",title:"删除"},on:{click:function(r){return t.deleteData(e.row)}}},[t._v("删除")])]}}])})],1),r("div",{staticClass:"block"},[r("el-pagination",{attrs:{background:"","page-sizes":[10,20,50],"page-size":t.searchForm.pageSize,"current-page":t.searchForm.pageNum,layout:"total, sizes, prev, pager, next, jumper",total:t.dataTotal},on:{"size-change":t.handleSizeChange,"current-change":t.handleCurrentChange}})],1),r("el-dialog",{attrs:{title:"添加端口",visible:t.addDialog,width:"30%"},on:{"update:visible":function(e){t.addDialog=e}}},[r("el-form",{ref:"addForm",attrs:{model:t.addForm,rules:t.addFormRules,"label-width":"120px",size:"small"}},[r("el-form-item",{attrs:{label:"所属服务器",prop:"serverId"}},[r("el-select",{staticStyle:{width:"100%"},attrs:{size:"mini",clearable:""},model:{value:t.addForm.serverId,callback:function(e){t.$set(t.addForm,"serverId",e)},expression:"addForm.serverId"}},t._l(t.serverList,(function(t,e){return r("el-option",{key:t+e,attrs:{label:t.serverName,value:t.id}})})),1)],1),r("el-form-item",{attrs:{label:"本地端口",prop:"localPort",rules:[{required:!0,message:"端口不能为空"},{type:"number",message:"端口必须为数字值"}]}},[r("el-input",{attrs:{size:"mini"},model:{value:t.addForm.localPort,callback:function(e){t.$set(t.addForm,"localPort",t._n(e))},expression:"addForm.localPort"}})],1),r("el-form-item",{attrs:{label:"外网端口",prop:"internetPort",rules:[{required:!0,message:"端口不能为空"},{type:"number",message:"端口必须为数字值"}]}},[r("el-input",{attrs:{size:"mini"},model:{value:t.addForm.internetPort,callback:function(e){t.$set(t.addForm,"internetPort",t._n(e))},expression:"addForm.internetPort"}})],1)],1),r("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[r("el-button",{on:{click:function(e){t.addDialog=!1}}},[t._v("取 消")]),r("el-button",{attrs:{type:"primary"},on:{click:t.confirmAddForm}},[t._v("确 定")])],1)],1)],1)},n=[],o=r("4731"),i=r("aa22"),s={data:function(){return{tableData:[],dataTotal:null,serverList:[],searchForm:{pageSize:10,pageNum:1},addForm:{id:null,username:null,addType:"add",password:null},addFormRules:{serverId:[{required:!0,trigger:"blur",message:"必需项"}],localPort:[{required:!0,trigger:"blur",message:"必需项"}],internetPort:[{required:!0,trigger:"blur",message:"必需项"}]},addDialog:!1}},mounted:function(){this.initServerList(),this.getData()},methods:{getData:function(){var t=this;Object(o["e"])(this.searchForm).then((function(e){t.tableData=e.data.list,t.dataTotal=e.data.total}))},deleteData:function(t){var e=this;this.$confirm("确认删除?",{confirmButtonText:"确认",cancelButtonText:"取消",type:"warning"}).then((function(){Object(o["deleteData"])({id:t.id}).then((function(t){e.$notify({message:"删除成功",type:"success"}),e.getData()}))}))},confirmAddForm:function(){var t=this;this.$refs["addForm"].validate((function(e){e&&Object(o["save"])(t.addForm).then((function(e){t.$notify({message:"保存成功",type:"success"}),t.addDialog=!1,t.getData()}))}))},handleSizeChange:function(t){this.searchForm.pageSize=t,this.getData()},handleCurrentChange:function(t){this.searchForm.pageNum=t,this.getData()},initServerList:function(){var t=this;Object(i["c"])().then((function(e){t.serverList=e.data}))},showAddDialog:function(){this.addDialog=!0,this.addForm.addType="add",this.addForm.id=null},showEditDialog:function(t){this.addDialog=!0,this.addForm=t,this.addForm.addType="edit"},copyRow:function(t){this.addDialog=!0,this.addForm=t,this.addForm.id=null,this.addForm.addType="add"}}},l=s,d=(r("4942"),r("2877")),u=Object(d["a"])(l,a,n,!1,null,"dac09a84",null);e["default"]=u.exports},ced1:function(t,e,r){}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-480b22f6.4f228d1f.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-480b22f6"],{"08db":function(t,a,e){"use strict";var r=e("2e6f"),s=e.n(r);s.a},"2e6f":function(t,a,e){},"52f9":function(t,a,e){"use strict";e.r(a);var r=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"app-container"},[e("div",{staticStyle:{"line-height":"50px",color:"#606266"}},[e("el-row",[t._v(" 如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 🍹, 你的支持是我继续更新的动力🙏🙏🙏 ")]),e("el-row",[e("img",{staticClass:"user-avatar",attrs:{src:"reward.gif",width:"200px"}})]),e("el-row",[e("el-col",[e("i",{staticClass:"el-icon-wallet"}),t._v(" "),e("a",{staticStyle:{color:"#1989fa"},attrs:{target:"_blank",href:"https://www.paypal.com/paypalme/MrTreeOLO",hre:""}},[t._v("PayPal打赏")])])],1),e("el-row",[e("i",{staticClass:"el-icon-milk-tea"}),t._v(" USDT打赏: "),e("a",{attrs:{hre:""}},[t._v("TEVJQK8iPr2aWEQJ89NTWtSP6bVc8G1xGu")])]),e("el-row",[e("img",{staticClass:"user-avatar",attrs:{src:"usdt.jpeg",width:"280px"}})])],1)])},s=[],l={data:function(){return{tableData:[],dataTotal:null}},mounted:function(){this.getData()},methods:{}},i=l,c=(e("08db"),e("2877")),n=Object(c["a"])(i,r,s,!1,null,"009db799",null);a["default"]=n.exports}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-632b8606.5ee39ba4.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-632b8606"],{"20ec":function(a,t,e){},"7a85":function(a,t,e){"use strict";var n=e("20ec"),c=e.n(n);c.a},9406:function(a,t,e){"use strict";e.r(t);var n=function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",{staticClass:"dashboard-container"},[e("div",{staticClass:"dashboard-text"},[a._v(a._s(a.name)+", 欢迎使用闲蛋中转")])])},c=[],s=e("5530"),i=e("2f62"),o={name:"Dashboard",computed:Object(s["a"])({},Object(i["b"])(["name"]))},r=o,u=(e("7a85"),e("2877")),d=Object(u["a"])(r,n,c,!1,null,"58607407",null);t["default"]=d.exports}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-76cea4de.78bea551.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-76cea4de"],{"26fc":function(t,s,e){t.exports=e.p+"static/img/404_cloud.0f4bc32b.png"},"8cdb":function(t,s,e){"use strict";e.r(s);var a=function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"wscn-http404-container"},[e("div",{staticClass:"wscn-http404"},[t._m(0),e("div",{staticClass:"bullshit"},[e("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._m(1),e("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),e("div",{staticClass:"bullshit__info"},[t._v("Please check that the URL you entered is correct, or click the button below to return to the homepage.")]),e("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("Back to home")])])])])},c=[function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"pic-404"},[a("img",{staticClass:"pic-404__parent",attrs:{src:e("a36b"),alt:"404"}}),a("img",{staticClass:"pic-404__child left",attrs:{src:e("26fc"),alt:"404"}}),a("img",{staticClass:"pic-404__child mid",attrs:{src:e("26fc"),alt:"404"}}),a("img",{staticClass:"pic-404__child right",attrs:{src:e("26fc"),alt:"404"}})])},function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"bullshit__info"},[t._v("All rights reserved "),e("a",{staticStyle:{color:"#20a0ff"},attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[t._v("wallstreetcn")])])}],i={name:"Page404",computed:{message:function(){return"The webmaster said that you can not enter this page..."}}},l=i,n=(e("97ef"),e("2877")),r=Object(n["a"])(l,a,c,!1,null,"c095f994",null);s["default"]=r.exports},"97ef":function(t,s,e){"use strict";var a=e("ed94"),c=e.n(a);c.a},a36b:function(t,s,e){t.exports=e.p+"static/img/404.a57b6f31.png"},ed94:function(t,s,e){}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-9fdcb8cc.b71478a3.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-9fdcb8cc"],{2017:function(e,s,t){"use strict";var n=t("cafe"),o=t.n(n);o.a},2155:function(e,s,t){"use strict";var n=t("ccec"),o=t.n(n);o.a},"9ed6":function(e,s,t){"use strict";t.r(s);var n=function(){var e=this,s=e.$createElement,t=e._self._c||s;return t("div",{staticClass:"login-container"},[t("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,"auto-complete":"on","label-position":"left"}},[t("div",{staticClass:"title-container"},[t("h3",{staticClass:"title"},[e._v("闲蛋中转面板")])]),t("el-form-item",{attrs:{prop:"username",rules:[{required:!0,message:"用户名不能为空"}]}},[t("span",{staticClass:"svg-container"},[t("svg-icon",{attrs:{"icon-class":"user"}})],1),t("el-input",{ref:"username",attrs:{placeholder:"用户名",name:"username",type:"text",tabindex:"1","auto-complete":"on"},model:{value:e.loginForm.username,callback:function(s){e.$set(e.loginForm,"username",s)},expression:"loginForm.username"}})],1),t("el-form-item",{attrs:{prop:"password"}},[t("span",{staticClass:"svg-container"},[t("svg-icon",{attrs:{"icon-class":"password"}})],1),t("el-input",{key:e.passwordType,ref:"password",attrs:{type:e.passwordType,placeholder:"密码",name:"password",tabindex:"2","auto-complete":"on"},nativeOn:{keyup:function(s){return!s.type.indexOf("key")&&e._k(s.keyCode,"enter",13,s.key,"Enter")?null:e.handleLogin(s)}},model:{value:e.loginForm.password,callback:function(s){e.$set(e.loginForm,"password",s)},expression:"loginForm.password"}}),t("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[t("svg-icon",{attrs:{"icon-class":"password"===e.passwordType?"eye":"eye-open"}})],1)],1),t("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(s){return s.preventDefault(),e.handleLogin(s)}}},[e._v("登录")])],1)],1)},o=[],r={name:"Login",data:function(){var e=function(e,s,t){s.length<4?t(new Error("请输入密码,最少6位")):t()};return{loginForm:{username:"",password:""},loginRules:{password:[{required:!0,trigger:"blur",validator:e}]},loading:!1,passwordType:"password",redirect:void 0}},watch:{$route:{handler:function(e){this.redirect=e.query&&e.query.redirect},immediate:!0}},methods:{showPwd:function(){var e=this;"password"===this.passwordType?this.passwordType="":this.passwordType="password",this.$nextTick((function(){e.$refs.password.focus()}))},handleLogin:function(){var e=this;this.$refs.loginForm.validate((function(s){if(!s)return console.log("error submit!!"),!1;e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then((function(){e.$router.push({path:e.redirect||"/"}),e.loading=!1})).catch((function(){e.loading=!1}))}))}}},a=r,i=(t("2017"),t("2155"),t("2877")),l=Object(i["a"])(a,n,o,!1,null,"69a56f99",null);s["default"]=l.exports},cafe:function(e,s,t){},ccec:function(e,s,t){}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/static/js/chunk-e732e32c.36ae8557.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e732e32c"],{"26b0":function(t,e,a){"use strict";a.r(e);var o=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"app-container"},[a("el-form",{ref:"form",staticStyle:{width:"400px","max-width":"98%"},attrs:{model:t.addForm,"label-width":"80px"}},[a("el-form-item",{attrs:{label:"系统升级"}},[a("el-button",{attrs:{size:"mini"},on:{click:t.exportSystemData}},[t._v("导出数据")]),a("el-button",{attrs:{type:"primary",size:"mini"},on:{click:t.importSystemData}},[t._v("导入数据")])],1),a("el-form-item",{attrs:{label:"当前版本:"}},[a("span",[t._v(t._s(t.addForm.version))])]),a("el-form-item",{attrs:{label:"TG:",prop:"telegram"}},[a("el-input",{attrs:{size:"mini",placeholder:"请输入tg链接,租户到期会弹框提示"},model:{value:t.addForm.telegram,callback:function(e){t.$set(t.addForm,"telegram",e)},expression:"addForm.telegram"}})],1),a("el-form-item",{attrs:{label:"QQ:",prop:"qq"}},[a("el-input",{attrs:{size:"mini",placeholder:"请输入qq号,租户到期会弹框提示"},model:{value:t.addForm.qq,callback:function(e){t.$set(t.addForm,"qq",e)},expression:"addForm.qq"}})],1),a("el-form-item",{attrs:{label:"邮箱:",prop:"email"}},[a("el-input",{attrs:{size:"mini",placeholder:"请输入邮箱地址,租户到期会弹框提示"},model:{value:t.addForm.email,callback:function(e){t.$set(t.addForm,"email",e)},expression:"addForm.email"}})],1),a("el-button",{staticStyle:{float:"right"},attrs:{size:"mini",type:"primary"},on:{click:t.saveSysConfig}},[t._v("保存配置")])],1),a("el-dialog",{attrs:{title:"导入数据",visible:t.importDialog,width:"30%"},on:{"update:visible":function(e){t.importDialog=e}}},[a("el-form",{ref:"addForm",attrs:{model:t.addForm,"label-width":"80px",size:"small"}},[a("el-form-item",{attrs:{label:"文件",prop:"addForm"}},[a("el-upload",{ref:"upload",staticClass:"upload-demo",attrs:{accept:".json",action:"/system/importData","http-request":t.customUpload,"auto-upload":!1,"show-file-list":!0,"file-list":t.addForm.fileList}},[a("el-button",{attrs:{size:"small",type:"primary"}},[t._v("选择文件")])],1)],1)],1),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(e){t.importDialog=!1}}},[t._v("取 消")]),a("el-button",{attrs:{type:"primary"},on:{click:t.confirmImport}},[t._v("确 定")])],1)],1)],1)},i=[],n=(a("d3b7"),a("3ca3"),a("ddb0"),a("2b3d"),a("8593")),r={data:function(){return{tableData:[],dataTotal:null,addForm:{id:null,telegram:null,qq:null,email:null,version:null},importDialog:!1}},mounted:function(){this.getSysConfig()},methods:{saveSysConfig:function(){var t=this;Object(n["d"])(this.addForm).then((function(e){t.$notify({message:"保存成功",type:"success"}),t.getSysConfig()}))},getSysConfig:function(){var t=this;Object(n["b"])({}).then((function(e){t.addForm=e.data}))},exportSystemData:function(){var t=this;Object(n["a"])({}).then((function(e){"0"===e.code?t.fileConversion("system-export-".concat((new Date).getTime(),".json"),JSON.stringify(e.data)):t.$notify({message:e.msg,type:"error"})})).catch((function(e){t.$notify({message:e.message,type:"error"})}))},importSystemData:function(){this.importDialog=!0},customUpload:function(t){var e=this;Object(n["c"])(t).then((function(t){e.importDialog=!1,e.$notify({message:"导入完成",type:"success"})}))},confirmImport:function(){this.$refs.upload.submit()},fileConversion:function(t,e){var a=t,o=new Blob([e],{type:"application/text"});if(window.navigator.msSaveOrOpenBlob)navigator.msSaveBlob(o);else{var i=document.createElement("a");i.download=a,i.style.display="none",i.href=URL.createObjectURL(o),document.body.appendChild(i),i.click(),document.body.removeChild(i)}}}},l=r,s=(a("e152"),a("2877")),m=Object(s["a"])(l,o,i,!1,null,"70b61e79",null);e["default"]=m.exports},8593:function(t,e,a){"use strict";a.d(e,"a",(function(){return r})),a.d(e,"c",(function(){return l})),a.d(e,"d",(function(){return s})),a.d(e,"b",(function(){return m}));var o=a("b775"),i=a("5a30"),n=a.n(i);function r(t){return Object(o["a"])({url:"/system/exportData",method:"get",params:t})}function l(t){var e=new n.a;return e.append("file",t.file),Object(o["a"])({method:"post",url:"/system/importData",headers:{"Content-Type":"multipart/form-data"},data:e})}function s(t){return Object(o["a"])({url:"/sysConfig/save",method:"post",data:t})}function m(t){return Object(o["a"])({url:"/sysConfig/getSysConfig",method:"get",params:t})}},"8fe1":function(t,e,a){},e152:function(t,e,a){"use strict";var o=a("8fe1"),i=a.n(o);i.a}}]);
--------------------------------------------------------------------------------
/src/main/resources/static/usdt.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noobcfy/forwordpanel/e12657eb02e35e54b8d66daed60b836488885c18/src/main/resources/static/usdt.jpeg
--------------------------------------------------------------------------------
/src/test/java/com/leeroy/forwordpanel/forwordpanel/ForwordpanelApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ForwordpanelApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/java/com/leeroy/forwordpanel/forwordpanel/MyUserInfo.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel;
2 |
3 | import com.jcraft.jsch.UserInfo;
4 |
5 | /**
6 | * This class provide interface to feedback information to the user.
7 | */
8 | public class MyUserInfo implements UserInfo {
9 | private String password;
10 |
11 | private String passphrase;
12 |
13 | @Override
14 | public String getPassphrase() {
15 | System.out.println("MyUserInfo.getPassphrase()");
16 | return null;
17 | }
18 |
19 | @Override
20 | public String getPassword() {
21 | System.out.println("MyUserInfo.getPassword()");
22 | return null;
23 | }
24 |
25 | @Override
26 | public boolean promptPassphrase(final String arg0) {
27 | System.out.println("MyUserInfo.promptPassphrase()");
28 | System.out.println(arg0);
29 | return false;
30 | }
31 |
32 | @Override
33 | public boolean promptPassword(final String arg0) {
34 | System.out.println("MyUserInfo.promptPassword()");
35 | System.out.println(arg0);
36 | return false;
37 | }
38 |
39 | @Override
40 | public boolean promptYesNo(final String arg0) {
41 | System.out.println("MyUserInfo.promptYesNo()");
42 | System.out.println(arg0);
43 | if (arg0.contains("The authenticity of host")) {
44 | return true;
45 | }
46 | return false;
47 | }
48 |
49 | @Override
50 | public void showMessage(final String arg0) {
51 | System.out.println("MyUserInfo.showMessage()");
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/test/java/com/leeroy/forwordpanel/forwordpanel/SSHCommandExecutor.java:
--------------------------------------------------------------------------------
1 | package com.leeroy.forwordpanel.forwordpanel;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.util.Vector;
6 |
7 | import com.jcraft.jsch.Channel;
8 | import com.jcraft.jsch.ChannelExec;
9 | import com.jcraft.jsch.JSch;
10 | import com.jcraft.jsch.JSchException;
11 | import com.jcraft.jsch.Session;
12 |
13 | /**
14 | * This class provide interface to execute command on remote Linux.
15 | */
16 |
17 | public class SSHCommandExecutor {
18 | private String ipAddress;
19 |
20 | private String username;
21 |
22 | private String password;
23 |
24 | public static final int DEFAULT_SSH_PORT = 34204;
25 |
26 | private Vector stdout;
27 |
28 | public SSHCommandExecutor(final String ipAddress, final String username, final String password) {
29 | this.ipAddress = ipAddress;
30 | this.username = username;
31 | this.password = password;
32 | stdout = new Vector<>();
33 | }
34 |
35 | public int execute(final String command) {
36 | int returnCode = 0;
37 | JSch jsch = new JSch();
38 | MyUserInfo userInfo = new MyUserInfo();
39 |
40 | try {
41 | // Create and connect session.
42 | Session session = jsch.getSession(username, ipAddress, DEFAULT_SSH_PORT);
43 | session.setPassword(password);
44 | session.setUserInfo(userInfo);
45 | session.connect();
46 |
47 | // Create and connect channel.
48 | Channel channel = session.openChannel("exec");
49 | ((ChannelExec) channel).setCommand(command);
50 |
51 | channel.setInputStream(null);
52 | BufferedReader input = new BufferedReader(new InputStreamReader(channel
53 | .getInputStream()));
54 |
55 | channel.connect();
56 | System.out.println("The remote command is: " + command);
57 |
58 | // Get the output of remote command.
59 | String line;
60 | while ((line = input.readLine()) != null) {
61 | stdout.add(line);
62 | }
63 | input.close();
64 |
65 | // Get the return code only after the channel is closed.
66 | if (channel.isClosed()) {
67 | returnCode = channel.getExitStatus();
68 | }
69 |
70 | // Disconnect the channel and session.
71 | channel.disconnect();
72 | session.disconnect();
73 | } catch (JSchException e) {
74 | // TODO Auto-generated catch block
75 | e.printStackTrace();
76 | } catch (Exception e) {
77 | e.printStackTrace();
78 | }
79 | return returnCode;
80 | }
81 |
82 | public Vector getResultSet() {
83 | return stdout;
84 | }
85 |
86 | public String getResult() {
87 | return stdout.get(0);
88 | }
89 |
90 | public static void main(final String [] args) {
91 | SSHCommandExecutor sshExecutor = new SSHCommandExecutor("120.241.154.4", "root", "28L8CegNk9");
92 | sshExecutor.execute(String.format("iptables -n -v -L -t filter -x | grep %s | awk '{print $2}'", "34.92.251.167"));
93 | System.out.println(sshExecutor.getResult());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------