├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
├── java
└── net
│ └── fangstar
│ └── wifi
│ └── portal
│ ├── Server.java
│ ├── controller
│ └── WiFiPortalController.java
│ └── util
│ ├── Codes.java
│ ├── Connections.java
│ ├── Requests.java
│ └── Result.java
└── resources
├── application.properties
├── db.properties
├── etc
└── header.txt
├── log4j.properties
└── portal.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | logs/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wifidog-java-portal
2 |
3 | ## 背景
4 |
5 | 在一些公共场所(比如公交车、地跌、机场等)连接当地的 WiFi 时会弹出一个验证表单,输入验证信息(比如短信验证码)后就能够通过该 WiFi 联网。
6 |
7 | ## WiFiDog
8 |
9 | WiFiDog 是一套开源的无线热点认证管理工具,它主要提供如下功能:
10 |
11 | 1. 位置相关的内容递送(比如不同的接入点可以投递不同的广告)
12 | 2. 用户认证和授权(认证方式可以通过短信,或者是基础第三方开放平台,比如 QQ、微信等,授权可通过流控实现)
13 | 3. 集中式网络监控(在认证服务器上可以获得各个 WiFi 热点上用户的流量使用情况)
14 |
15 | WiFiDog 在架构上分为两个部分:
16 |
17 | * Gateway:即安装在路由器上的 WiFiDog 软件
18 | * Captive Portal:即认证服务器(AuthServer),是 Web HTTP 服务,独立部署在公网上
19 |
20 | 为了启用认证功能,我们需要对 WiFiDog 进行一点配置,修改配置文件 /etc/wifidog.conf,找到 AuthServer,并取消其中的几行注释:
21 |
22 | ```
23 | AuthServer {
24 | Hostname 192.168.1.109
25 | # SSLAvailable
26 | # SSLPort
27 | HTTPPort 8910
28 | # Path
29 | # LoginScriptPathFragment
30 | # PortalScriptPathFragment
31 | # MsgScriptPathFragment
32 | # PingScriptPathFragment
33 | # AuthScriptPathFragment
34 | }
35 |
36 | ```
37 |
38 | 为了简便,其他的配置项我们都用默认的。修改后重启 WiFiDog:/etc/init.d/wifidog restart
39 |
40 | ## 认证协议
41 |
42 | WiFiDog v1 协议是目前(2016)使用最广泛的,协议流程如下(红色部分即认证服务需要实现的接口):
43 |
44 | 
45 |
46 | 1. GW(Gateway) 会定时调用 AS(AuthServer) 的 ping 接口来检查 AS 是否在线
47 | 1.1. AS 在响应 body 里写入 "Pong"
48 | 2. 用户连上 GW 后,通过浏览器发出对某站点的请求
49 | 2.1. GW 收到请求后发现用户没有认证过,则重定向用户到 AS 的 /login
50 | 3. 浏览器请求 AS 的 /login
51 | 3.1. AS 返回验证表单 HTML
52 | 4. 用户填写验证表单后提交 AS
53 | 4.1. AS 验证通过后生成 token 并重定向用户到 GW
54 | 5. 浏览器带 token 请求 GW 的验证接口
55 | 5.1. GW 获取用户 token 后再请求 AS /auth 接口
56 | 5.2. AS 验证 token 有效性,成功则返回 "Auth: 1"(注意空格),验证通过后 GW 会定时请求 AS 的 /auth 接口来检查 token 有效性,期间会带上用户的流量数据
57 | 5.3. GW 重定向用户到 AS /portal
58 | 6. 浏览器请求 GW 的 /portal 接口
59 | 6.1 AS 重定向用户到 2 中指定的某站点(也可以按需进行广告投放)
60 |
61 | ## 报文详解
62 |
63 | 基于 WiFiDog 1.2.1 整理,192.168.1.1 是路由 IP,192.168.1.109 同时是客户端和 AuthServer 的 IP。
64 |
65 | ### ping
66 |
67 | ```
68 | request [
69 | URI=/wifidog/ping/
70 | method=GET
71 | remoteAddr=192.168.1.1
72 | queryStr=gw_id=100D7F6F25F5&sys_uptime=7265&sys_memfree=95256&sys_load=0.03&wifidog_uptime=61
73 | headers=[
74 | user-agent=WiFiDog 1.2.1
75 | host=192.168.1.109
76 | ]
77 | ]
78 | ```
79 |
80 | GW 将系路由标识、负载情况传给 AuthSer,可以基于这些数据做监控。
81 |
82 | ### login
83 |
84 | ```
85 | request [
86 | URI=/wifidog/login/
87 | method=GET
88 | remoteAddr=192.168.1.109
89 | queryStr=gw_address=192.168.1.1&gw_port=2060&gw_id=100D7F6F25F5&ip=192.168.1.109&mac=64:00:6a:5d:0a:23&url=http%3A%2F%2Ffangstar.net%2F
90 | headers=[
91 | host=192.168.1.109:8910
92 | connection=keep-alive
93 | upgrade-insecure-requests=1
94 | user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
95 | accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
96 | accept-encoding=gzip, deflate, sdch
97 | accept-language=zh-CN,zh;q=0.8,da;q=0.6,en;q=0.4,id;q=0.2,ja;q=0.2,sq;q=0.2,zh-TW;q=0.2,en-US;q=0.2
98 | cookie=JSESSIONID=3AE20A3B0636E2F7DB7247AD055491FE
99 | ]
100 | ]
101 | ```
102 |
103 | 查询参数中的 url 是用户要访问的目标站点。
104 |
105 | ### auth
106 |
107 | ```
108 | request [
109 | URI=/wifidog/auth/
110 | method=GET
111 | remoteAddr=192.168.1.1
112 | queryStr=stage=login&ip=192.168.1.109&mac=64:00:6a:5d:0a:23&token=22&incoming=0&outgoing=0&gw_id=100D7F6F25F5
113 | headers=[
114 | user-agent=WiFiDog 1.2.1
115 | host=192.168.1.109
116 | ]
117 | ]
118 | ```
119 | * stage:第一次认证是 login,后续定时轮询是 counters
120 | * incoming/outgoing:用户流量
121 |
122 | ### portal
123 |
124 | ```
125 | request [
126 | URI=/wifidog/portal/
127 | method=GET
128 | remoteAddr=192.168.1.109
129 | queryStr=gw_id=100D7F6F25F5
130 | headers=[
131 | host=192.168.1.109:8910
132 | connection=keep-alive
133 | cache-control=max-age=0
134 | upgrade-insecure-requests=1
135 | user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
136 | accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
137 | referer=http://192.168.1.109:8910/wifidog/login/?gw_address=192.168.1.1&gw_port=2060&gw_id=100D7F6F25F5&ip=192.168.1.109&mac=64:00:6a:5d:0a:23&url=http%3A%2F%2Ffangstar.net%2F
138 | accept-encoding=gzip, deflate, sdch
139 | accept-language=zh-CN,zh;q=0.8,da;q=0.6,en;q=0.4,id;q=0.2,ja;q=0.2,sq;q=0.2,zh-TW;q=0.2,en-US;q=0.2
140 | cookie=JSESSIONID=3AE20A3B0636E2F7DB7247AD055491FE
141 | ]
142 | ]
143 | ```
144 |
145 |
146 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 | 4.0.0
11 | net.fangstar.wifi
12 | portal
13 | 1.0.0
14 | jar
15 | WiFiPortal
16 |
17 |
18 | org.springframework.boot
19 | spring-boot-starter-parent
20 | 1.3.3.RELEASE
21 |
22 |
23 |
24 | UTF-8
25 | 1.7
26 | 1.7
27 |
28 |
29 | 1.0.16
30 |
31 | 5.1.37
32 |
33 | net.fangstar.wifi.portal.Server
34 |
35 | 1.8.3
36 | 20160212
37 | 1.6
38 | 2.6
39 | 1.2
40 | 2.4
41 | 1.10
42 | 1.7.21
43 |
44 | 1.9.0
45 |
46 |
47 |
48 |
49 |
50 | com.alibaba
51 | druid
52 | ${druid.version}
53 |
54 |
55 |
56 | mysql
57 | mysql-connector-java
58 | ${mysql-connector-java.version}
59 |
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-starter-web
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-starter-logging
68 |
69 |
70 |
71 |
72 |
73 | org.jsoup
74 | jsoup
75 | ${jsoup.version}
76 |
77 |
78 |
79 | commons-dbutils
80 | commons-dbutils
81 | ${commons-dbutils.version}
82 |
83 |
84 |
85 | commons-lang
86 | commons-lang
87 | ${commons-lang.version}
88 |
89 |
90 |
91 | commons-logging
92 | commons-logging
93 | ${commons-logging.version}
94 |
95 |
96 |
97 | commons-io
98 | commons-io
99 | ${commons-io.version}
100 |
101 |
102 |
103 | org.slf4j
104 | slf4j-log4j12
105 | ${slf4j.version}
106 |
107 |
108 |
109 | org.json
110 | json
111 | ${json.version}
112 |
113 |
114 |
115 | commons-codec
116 | commons-codec
117 | ${commons-codec.version}
118 |
119 |
120 |
121 |
122 |
123 | wifiportal
124 |
125 |
126 |
127 | src/main/resources
128 |
129 | etc/
130 | lib/
131 |
132 |
133 |
134 |
135 |
136 |
137 | org.springframework.boot
138 | spring-boot-maven-plugin
139 |
140 |
141 |
142 |
143 | com.mycila.maven-license-plugin
144 | maven-license-plugin
145 | ${maven-license-plugin.version}
146 |
147 | src/main/resources/etc/header.txt
148 | false
149 | true
150 | true
151 | true
152 |
153 | **/src/*/java/**/*.java
154 | **/src/*/resources/**/*.properties
155 |
156 |
157 | **/src/main/java/**/package-info.java
158 | **/src/main/java/com/**/*.java
159 |
160 |
161 | true
162 |
163 | SLASHSTAR_STYLE
164 |
165 | true
166 |
167 | 2016
168 | fangstar.com
169 |
170 | ${project.build.sourceEncoding}
171 |
172 |
173 |
174 | generate-sources
175 |
176 | format
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/Server.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal;
7 |
8 | import java.util.ResourceBundle;
9 |
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 | import org.springframework.boot.SpringApplication;
13 | import org.springframework.boot.autoconfigure.SpringBootApplication;
14 |
15 | /**
16 | * WiFiPortal 服务.
17 | *
18 | * @author Liang Ding
19 | * @version 1.0.0.0, Aug 1, 2016
20 | * @since 1.0.0
21 | */
22 | @SpringBootApplication
23 | public class Server {
24 |
25 | /**
26 | * Logger.
27 | */
28 | private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
29 |
30 | /**
31 | * 配置.
32 | */
33 | public static final ResourceBundle CONF = ResourceBundle.getBundle("portal");
34 |
35 | /**
36 | * 程序入口.
37 | *
38 | * @param args 指定的命令行参数,不需要传
39 | * @throws Exception
40 | */
41 | public static void main(final String[] args) throws Exception {
42 | SpringApplication.run(Server.class);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/controller/WiFiPortalController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal.controller;
7 |
8 | import java.io.PrintWriter;
9 | import java.util.Enumeration;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import javax.servlet.http.HttpSession;
13 | import net.fangstar.wifi.portal.Server;
14 | import org.apache.commons.lang.StringUtils;
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 | import org.springframework.stereotype.Controller;
18 | import org.springframework.web.bind.annotation.RequestMapping;
19 | import org.springframework.web.bind.annotation.RequestMethod;
20 |
21 | /**
22 | * WiFiPortal 控制器.
23 | *
24 | * @author Liang Ding
25 | * @version 1.0.0.0, Aug 1, 2016
26 | * @since 1.0.0
27 | */
28 | @Controller
29 | @RequestMapping("/wifidog")
30 | public class WiFiPortalController {
31 |
32 | /**
33 | * Logger.
34 | */
35 | private static final Logger LOGGER = LoggerFactory.getLogger(WiFiPortalController.class);
36 |
37 | /**
38 | * WiFiDog 网关地址.
39 | */
40 | private static final String GATEWAY_ADDR = Server.CONF.getString("gateway.addr");
41 |
42 | /**
43 | * Portal 地址.
44 | */
45 | private static final String PORTAL_ADDR = Server.CONF.getString("portal.addr");
46 |
47 | /**
48 | * Test token.
49 | */
50 | private static final String TOKEN = "33";
51 |
52 | @RequestMapping(value = "/login", method = RequestMethod.GET)
53 | public void showLogin(final HttpServletRequest request, final HttpServletResponse response) {
54 | logReq(request);
55 |
56 | try (final PrintWriter writer = response.getWriter()) {
57 | final HttpSession session = request.getSession();
58 | String visitURL = (String) session.getAttribute("url");
59 | if (StringUtils.isBlank(visitURL)) {
60 | visitURL = request.getParameter("url");
61 | }
62 | session.setAttribute("url", visitURL);
63 |
64 | writer.write(" \n"
65 | + "
\n"
66 | + " \n"
67 | + " 登录 - Portal\n"
68 | + " \n"
69 | + " \n"
70 | + " \n"
77 | + " \n"
78 | + "");
79 |
80 | writer.flush();
81 | } catch (final Exception e) {
82 | LOGGER.error("Write response failed", e);
83 | }
84 | }
85 |
86 | @RequestMapping(value = "/login", method = RequestMethod.POST)
87 | public void login(final HttpServletRequest request, final HttpServletResponse response) {
88 | logReq(request);
89 |
90 | try {
91 | response.sendRedirect(GATEWAY_ADDR + "/wifidog/auth?token=" + TOKEN);
92 | } catch (final Exception e) {
93 | LOGGER.error("Write response failed", e);
94 | }
95 | }
96 |
97 | @RequestMapping(value = "/auth", method = {RequestMethod.POST, RequestMethod.GET})
98 | public void auth(final HttpServletRequest request, final HttpServletResponse response) {
99 | logReq(request);
100 |
101 | try (final PrintWriter writer = response.getWriter()) {
102 | final String token = request.getParameter("token");
103 | if (TOKEN.equals(token)) {
104 | writer.write("Auth: 1");
105 | } else {
106 | writer.write("Auth: 0");
107 | }
108 |
109 | writer.flush();
110 | } catch (final Exception e) {
111 | LOGGER.error("Write response failed", e);
112 | }
113 | }
114 |
115 | @RequestMapping(value = "portal", method = {RequestMethod.POST, RequestMethod.GET})
116 | public void portal(final HttpServletRequest request, final HttpServletResponse response) {
117 | logReq(request);
118 |
119 | try {
120 | final String visitURL = (String) request.getSession().getAttribute("url");
121 |
122 | response.sendRedirect(visitURL);
123 | } catch (final Exception e) {
124 | LOGGER.error("Write response failed", e);
125 | }
126 | }
127 |
128 | @RequestMapping(value = "ping", method = {RequestMethod.POST, RequestMethod.GET})
129 | public void ping(final HttpServletRequest request, final HttpServletResponse response) {
130 | logReq(request);
131 |
132 | try (final PrintWriter writer = response.getWriter()) {
133 | writer.write("Pong");
134 | writer.flush();
135 | } catch (final Exception e) {
136 | LOGGER.error("Write response failed", e);
137 | }
138 | }
139 |
140 | private void logReq(final HttpServletRequest request) {
141 | final StringBuilder reqBuilder = new StringBuilder("\nrequest [\n URI=")
142 | .append(request.getRequestURI())
143 | .append("\n method=").append(request.getMethod())
144 | .append("\n remoteAddr=").append(request.getRemoteAddr());
145 |
146 | final String queryStr = request.getQueryString();
147 | if (StringUtils.isNotBlank(queryStr)) {
148 | reqBuilder.append("\n queryStr=").append(queryStr);
149 | }
150 |
151 | final StringBuilder headerBuilder = new StringBuilder();
152 | final Enumeration headerNames = request.getHeaderNames();
153 | while (headerNames.hasMoreElements()) {
154 | final String headerName = headerNames.nextElement();
155 | final String headerValue = request.getHeader(headerName);
156 |
157 | headerBuilder.append(" ").append(headerName).append("=").append(headerValue).append("\n");
158 | }
159 | headerBuilder.append(" ]");
160 | reqBuilder.append("\n headers=[\n").append(headerBuilder.toString()).append("\n]");
161 |
162 | LOGGER.debug(reqBuilder.toString());
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/util/Codes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal.util;
7 |
8 | import java.security.SecureRandom;
9 | import javax.crypto.Cipher;
10 | import javax.crypto.KeyGenerator;
11 | import javax.crypto.SecretKey;
12 | import javax.crypto.spec.SecretKeySpec;
13 | import org.apache.commons.codec.binary.Hex;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | /**
18 | * 编码工具.
19 | *
20 | * @author Liang Ding
21 | * @version 1.0.1.0, Jun 13, 2016
22 | * @since 1.0.0
23 | */
24 | public final class Codes {
25 |
26 | /**
27 | * Logger.
28 | */
29 | private static final Logger LOGGER = LoggerFactory.getLogger(Codes.class);
30 |
31 | /**
32 | * AES 加密.
33 | *
34 | * @param content 指定的加密内容(明文)
35 | * @param key 指定的密钥
36 | * @return 加密结果(密文)
37 | * @see #decryptByAES(java.lang.String, java.lang.String)
38 | */
39 | public static String encryptByAES(final String content, final String key) {
40 | try {
41 | final KeyGenerator kgen = KeyGenerator.getInstance("AES");
42 | final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
43 | secureRandom.setSeed(key.getBytes());
44 | kgen.init(128, secureRandom);
45 | final SecretKey secretKey = kgen.generateKey();
46 | final byte[] enCodeFormat = secretKey.getEncoded();
47 | final SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
48 | final Cipher cipher = Cipher.getInstance("AES");
49 | final byte[] byteContent = content.getBytes("UTF-8");
50 | cipher.init(Cipher.ENCRYPT_MODE, keySpec);
51 | final byte[] result = cipher.doFinal(byteContent);
52 |
53 | return Hex.encodeHexString(result);
54 | } catch (final Exception e) {
55 | LOGGER.error("Encrypt failed", e);
56 |
57 | return null;
58 | }
59 | }
60 |
61 | /**
62 | * AES 解密.
63 | *
64 | * @param content 指定的解密内容(密文)
65 | * @param key 指定的密钥
66 | * @return 解密结果(明文)
67 | * @see #encryptByAES(java.lang.String, java.lang.String)
68 | */
69 | public static String decryptByAES(final String content, final String key) {
70 | try {
71 | final byte[] data = Hex.decodeHex(content.toCharArray());
72 | final KeyGenerator kgen = KeyGenerator.getInstance("AES");
73 | final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
74 | secureRandom.setSeed(key.getBytes());
75 | kgen.init(128, secureRandom);
76 | final SecretKey secretKey = kgen.generateKey();
77 | final byte[] enCodeFormat = secretKey.getEncoded();
78 | final SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
79 | final Cipher cipher = Cipher.getInstance("AES");
80 | cipher.init(Cipher.DECRYPT_MODE, keySpec);
81 | final byte[] result = cipher.doFinal(data);
82 |
83 | return new String(result, "UTF-8");
84 | } catch (final Exception e) {
85 | LOGGER.error("Decrypt failed", e);
86 |
87 | return null;
88 | }
89 | }
90 |
91 | private Codes() {
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/util/Connections.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal.util;
7 |
8 | import com.alibaba.druid.pool.DruidDataSourceFactory;
9 | import java.sql.Connection;
10 | import java.sql.SQLException;
11 | import java.util.Properties;
12 | import javax.sql.DataSource;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | /**
17 | * 数据库连接工具类.
18 | *
19 | * @author Liang Ding
20 | * @version 1.0.0.0, Nov 2, 2015
21 | * @since 1.0.0
22 | */
23 | public final class Connections {
24 |
25 | /**
26 | * Logger.
27 | */
28 | private static final Logger LOGGER = LoggerFactory.getLogger(Connections.class);
29 |
30 | /**
31 | * 数据源.
32 | */
33 | private static DataSource dataSource;
34 |
35 | static {
36 | final ClassLoader classLoader = Connections.class.getClassLoader();
37 |
38 | try {
39 | final Properties props = new Properties();
40 | props.load(classLoader.getResourceAsStream("db.properties"));
41 |
42 | dataSource = DruidDataSourceFactory.createDataSource(props);
43 | } catch (final Exception e) {
44 | LOGGER.error("Reading DB configurations failed, exit Portal", e);
45 |
46 | System.exit(-1);
47 | }
48 | }
49 |
50 | /**
51 | * 获取一个数据库连接.
52 | *
53 | * @return 数据源连接
54 | * @throws SQLException 如果获取异常
55 | */
56 | public static Connection getConnection() throws SQLException {
57 | return dataSource.getConnection();
58 | }
59 |
60 | /**
61 | * 私有的构造器.
62 | */
63 | private Connections() {
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/util/Requests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal.util;
7 |
8 | import javax.servlet.http.HttpServletRequest;
9 | import org.apache.commons.lang.StringUtils;
10 |
11 | /**
12 | * HTTP 请求相关工具.
13 | *
14 | * @author Liang Ding
15 | * @version 1.0.0.0, Jun 27, 2016
16 | * @since 1.0.0
17 | */
18 | public class Requests {
19 |
20 | /**
21 | * Gets the Internet Protocol (IP) address of the end-client that sent the specified request.
22 | *
23 | *
24 | * It will try to get HTTP head "X-forwarded-for" or "X-Real-IP" from the last proxy to get the request first, if
25 | * not found, try to get it directly by {@link HttpServletRequest#getRemoteAddr()}.
26 | *
27 | *
28 | * @param request the specified request
29 | * @return the IP address of the end-client sent the specified request
30 | */
31 | public static String getRemoteAddr(final HttpServletRequest request) {
32 | String ret = request.getHeader("X-forwarded-for");
33 |
34 | if (StringUtils.isBlank(ret)) {
35 | ret = request.getHeader("X-Real-IP");
36 | }
37 |
38 | if (StringUtils.isBlank(ret)) {
39 | return request.getRemoteAddr();
40 | }
41 |
42 | return ret.split(",")[0];
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/net/fangstar/wifi/portal/util/Result.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, fangstar.com
3 | *
4 | * All rights reserved.
5 | */
6 | package net.fangstar.wifi.portal.util;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | /**
12 | * HTTP 调用结果.
13 | *
14 | * @author Liang Ding
15 | * @version 1.1.0.0, Nov 20, 2015
16 | * @since 1.0.0
17 | */
18 | public class Result {
19 |
20 | private int result;
21 | private int errorcode;
22 | private Map data = new HashMap<>();
23 |
24 | public int getResult() {
25 | return result;
26 | }
27 |
28 | public void setResult(int result) {
29 | this.result = result;
30 | }
31 |
32 | public int getErrorcode() {
33 | return errorcode;
34 | }
35 |
36 | public void setErrorcode(int errorcode) {
37 | this.errorcode = errorcode;
38 | }
39 |
40 | public Map getData() {
41 | return data;
42 | }
43 |
44 | public void setData(Map data) {
45 | this.data = data;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016, fangstar.com
3 | #
4 | # All rights reserved.
5 | #
6 |
7 | #
8 | # Description: Spring Boot configurations.
9 | # Version: 1.0.0.0, Aug 1, 2016
10 | # Author: Liang Ding
11 | #
12 |
13 | server.port=8910
14 | server.tomcat.max-threads=500
15 |
--------------------------------------------------------------------------------
/src/main/resources/db.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016, fangstar.com
3 | #
4 | # All rights reserved.
5 | #
6 |
7 | #
8 | # Description: Database configurations.
9 | # Version: 1.0.0.1, Jun 14, 2016
10 | # Author: Liang Ding
11 | #
12 |
13 | #url=jdbc:mysql://192.168.10.21:3306/wifiportal?useUnicode=yes&characterEncoding=utf8
14 | url=jdbc:mysql://127.0.0.1:3306/wifiportal?useUnicode=yes&characterEncoding=utf8
15 | username=wifiportal
16 | password=wifiportal
17 |
18 | validationQuery=SELECT 1
19 | maxActive=5
20 | minIdle=5
21 | defaultAutoCommit=false
22 |
--------------------------------------------------------------------------------
/src/main/resources/etc/header.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) ${year}, ${devTeam}
2 |
3 | All rights reserved.
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016, fangstar.com
3 | #
4 | # All rights reserved.
5 | #
6 |
7 | #
8 | # Description: Logging configurations.
9 | # Version: 1.0.0.1, Jun 23, 2016
10 | # Author: Liang Ding
11 | #
12 |
13 | log4j.rootLogger=DEBUG, stdout, file
14 |
15 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
16 | log4j.appender.stdout.Target=System.out
17 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 | log4j.appender.stdout.layout.ConversionPattern=[%-5p]-[%d{yyyy-MM-dd HH:mm:ss}]-[%c:%L]: %m%n
19 |
20 | log4j.appender.file=org.apache.log4j.RollingFileAppender
21 | log4j.appender.file.File=./logs/portal.log
22 | log4j.appender.file.MaxFileSize=10MB
23 | log4j.appender.file.MaxBackupIndex=5
24 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
25 | log4j.appender.file.layout.ConversionPattern=[%-5p]-[%d{yyyy-MM-dd HH:mm:ss}]-[%c:%L]: %m%n
26 |
27 | log4j.logger.com.alibaba=WARN
28 |
29 | log4j.logger.org.apache=ERROR
30 | log4j.logger.org.springframework=WARN
31 | log4j.logger.org.hibernate=WARN
32 | log4j.logger.org.jboss=WARN
33 |
--------------------------------------------------------------------------------
/src/main/resources/portal.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016, fangstar.com
3 | #
4 | # All rights reserved.
5 | #
6 |
7 | #
8 | # Description: WiFiPortal configurations.
9 | # Version: 1.0.0.0, Aug 1, 2016
10 | # Author: Liang Ding
11 | #
12 |
13 | portal.addr=http://192.168.1.142:8910
14 | # test env
15 | #portal.addr=http://120.25.81.140:8910
16 |
17 | gateway.addr=http://192.168.1.1:2060
--------------------------------------------------------------------------------