├── .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 | ![1470207764317](https://img.hacpai.com/d4b1f076eae04cb0a6565809dd87b53c.png) 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" 71 | + " \n" 73 | + " \n" 75 | + " \n" 76 | + "
\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 --------------------------------------------------------------------------------