├── .gitignore ├── LICENSE ├── LICENSE.996icu ├── LICENSE.mit ├── README.md ├── assembly └── bin.xml ├── doc ├── args.txt ├── cookie.txt ├── file.txt ├── flamegraph.svg ├── framegraph.png ├── ip.txt ├── post.txt ├── ua.txt ├── url.txt ├── wip.txt └── wurl.txt ├── pom.xml └── src ├── main ├── groovy │ └── info │ │ └── yangguo │ │ └── waf │ │ └── script │ │ ├── GroovySandbox.groovy │ │ └── ScriptEntry.groovy ├── java │ ├── info │ │ └── yangguo │ │ │ └── waf │ │ │ ├── Application.java │ │ │ ├── Constant.java │ │ │ ├── HostResolverImpl.java │ │ │ ├── HttpFilterAdapterImpl.java │ │ │ ├── WafHttpHeaderNames.java │ │ │ ├── config │ │ │ ├── AdminProperties.java │ │ │ ├── ClusterProperties.java │ │ │ ├── ContextHolder.java │ │ │ ├── CustomErrorController.java │ │ │ ├── ExceptionHandlerAdvice.java │ │ │ ├── LoginInterceptor.java │ │ │ └── WebConfig.java │ │ │ ├── controller │ │ │ ├── ConfigController.java │ │ │ └── UserController.java │ │ │ ├── dto │ │ │ ├── ForwardConfigDto.java │ │ │ ├── ForwardConfigItemDto.java │ │ │ ├── RedirectConfigDto.java │ │ │ ├── ResponseConfigDto.java │ │ │ ├── ResultDto.java │ │ │ ├── RewriteConfigDto.java │ │ │ ├── SecurityConfigDto.java │ │ │ ├── SecurityConfigItemDto.java │ │ │ ├── UpstreamConfigDto.java │ │ │ ├── UpstreamServerConfigDto.java │ │ │ └── UserDto.java │ │ │ ├── exception │ │ │ └── UnauthorizedException.java │ │ │ ├── model │ │ │ ├── BasicConfig.java │ │ │ ├── Config.java │ │ │ ├── ForwardConfig.java │ │ │ ├── ForwardConfigItem.java │ │ │ ├── ForwardType.java │ │ │ ├── ResponseConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityConfigItem.java │ │ │ ├── ServerBasicConfig.java │ │ │ ├── ServerConfig.java │ │ │ ├── UpstreamConfig.java │ │ │ └── WeightedRoundRobinScheduling.java │ │ │ ├── request │ │ │ ├── RedirectFilter.java │ │ │ ├── RequestFilter.java │ │ │ ├── RewriteFilter.java │ │ │ ├── SecurityFilter.java │ │ │ ├── TranslateFilter.java │ │ │ ├── security │ │ │ │ ├── ArgsSecurity.java │ │ │ │ ├── CCSecurity.java │ │ │ │ ├── CookieSecurity.java │ │ │ │ ├── FileSecurity.java │ │ │ │ ├── IpSecurity.java │ │ │ │ ├── PostSecurity.java │ │ │ │ ├── ScannerSecurity.java │ │ │ │ ├── ScriptSecurity.java │ │ │ │ ├── Security.java │ │ │ │ ├── UaSecurity.java │ │ │ │ ├── UrlSecurity.java │ │ │ │ ├── WIpSecurity.java │ │ │ │ └── WUrlSecurity.java │ │ │ └── translate │ │ │ │ ├── TranslateProcess.java │ │ │ │ ├── dubbo │ │ │ │ ├── HelloService.java │ │ │ │ └── HelloServiceTranslate.java │ │ │ │ ├── grpc │ │ │ │ └── HelloServiceTranslate.java │ │ │ │ └── http │ │ │ │ └── Swagger2Translate.java │ │ │ ├── response │ │ │ ├── ClickjackResponseProcess.java │ │ │ ├── HttpResponseFilter.java │ │ │ └── ResponseProcess.java │ │ │ ├── service │ │ │ ├── ClusterService.java │ │ │ ├── JwtTokenService.java │ │ │ └── ZkClusterService.java │ │ │ ├── util │ │ │ ├── JCEUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── NetUtils.java │ │ │ ├── PooledAllocatorStats.java │ │ │ ├── PropertiesUtil.java │ │ │ ├── ResponseUtil.java │ │ │ └── WafSelfSignedSslEngineSource.java │ │ │ └── validator │ │ │ ├── CheckRedirectConfigItem.java │ │ │ ├── CheckRewriteConfigItem.java │ │ │ ├── CheckSecurityConfigItem.java │ │ │ ├── Exist.java │ │ │ ├── ExistSequence.java │ │ │ ├── NotExist.java │ │ │ ├── NotExistSequence.java │ │ │ ├── RedirectConfigItemValidator.java │ │ │ ├── RewriteConfigItemValidator.java │ │ │ └── SecurityConfigItemValidator.java │ └── org │ │ └── littleshoot │ │ └── proxy │ │ └── impl │ │ ├── ClientToProxyConnection.java │ │ ├── ProxyConnection.java │ │ └── ProxyToServerConnection.java ├── proto │ └── helloworld.proto └── resources │ ├── META-INF │ └── services │ │ └── info.yangguo.waf.service.ClusterService │ ├── server1 │ ├── ESAPI.properties │ ├── admin.properties │ ├── api-docs │ │ └── 127.0.0.1:9091.json │ ├── application.properties │ ├── cluster.properties │ ├── logback.xml │ ├── script │ │ └── login.groovy │ ├── spring │ │ └── applicationContext.xml │ └── waf.properties │ ├── server2 │ ├── ESAPI.properties │ ├── admin.properties │ ├── application.properties │ ├── cluster.properties │ ├── logback.xml │ ├── script │ │ └── login.groovy │ ├── spring │ │ └── applicationContext.xml │ ├── upstream.properties │ └── waf.properties │ └── server3 │ ├── ESAPI.properties │ ├── admin.properties │ ├── application.properties │ ├── cluster.properties │ ├── logback.xml │ ├── script │ └── login.groovy │ ├── spring │ └── applicationContext.xml │ ├── upstream.properties │ └── waf.properties └── test ├── java └── info │ └── yangguo │ └── waf │ ├── IPTest.java │ ├── NetUtilsTest.java │ ├── Socks5Test.java │ ├── WeightedRoundRobinSchedulingTest.java │ └── request │ └── translate │ ├── dubbo │ └── Provider.java │ └── grpc │ └── Provider.java └── resources └── log4j.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | */target/ 3 | */.idea/* 4 | /.settings/* 5 | */.settings/* 6 | *.classpath 7 | *.project 8 | *.iml 9 | *.ipr 10 | *.iws 11 | classes/ 12 | disconf/ 13 | log/ 14 | .idea/* 15 | *.jks 16 | *.crt 17 | *.pem 18 | *.p12 19 | standlone/* 20 | metadata/* 21 | *.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | `SPDX-License-Identifier: MIT and 996ICU` 2 | -------------------------------------------------------------------------------- /LICENSE.996icu: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | "Anti 996" License Version 1.0 (Draft) 4 | 5 | Permission is hereby granted to any individual or legal entity 6 | obtaining a copy of this licensed work (including the source code, 7 | documentation and/or related items, hereinafter collectively referred 8 | to as the "licensed work"), free of charge, to deal with the licensed 9 | work for any purpose, including without limitation, the rights to use, 10 | reproduce, modify, prepare derivative works of, distribute, publish 11 | and sublicense the licensed work, subject to the following conditions: 12 | 13 | 1. The individual or the legal entity must conspicuously display, 14 | without modification, this License and the notice on each redistributed 15 | or derivative copy of the Licensed Work. 16 | 17 | 2. The individual or the legal entity must strictly comply with all 18 | applicable laws, regulations, rules and standards of the jurisdiction 19 | relating to labor and employment where the individual is physically 20 | located or where the individual was born or naturalized; or where the 21 | legal entity is registered or is operating (whichever is stricter). In 22 | case that the jurisdiction has no such laws, regulations, rules and 23 | standards or its laws, regulations, rules and standards are 24 | unenforceable, the individual or the legal entity are required to 25 | comply with Core International Labor Standards. 26 | 27 | 3. The individual or the legal entity shall not induce, suggest or force 28 | its employee(s), whether full-time or part-time, or its independent 29 | contractor(s), in any methods, to agree in oral or written form, to 30 | directly or indirectly restrict, weaken or relinquish his or her 31 | rights or remedies under such laws, regulations, rules and standards 32 | relating to labor and employment as mentioned above, no matter whether 33 | such written or oral agreements are enforceable under the laws of the 34 | said jurisdiction, nor shall such individual or the legal entity 35 | limit, in any methods, the rights of its employee(s) or independent 36 | contractor(s) from reporting or complaining to the copyright holder or 37 | relevant authorities monitoring the compliance of the license about 38 | its violation(s) of the said license. 39 | 40 | THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 43 | IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, 44 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 45 | OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE 46 | LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. 47 | -------------------------------------------------------------------------------- /LICENSE.mit: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | release 7 | true 8 | 9 | 10 | zip 11 | 12 | 13 | 14 | target/jsw/waf 15 | / 16 | 0777 17 | 18 | 19 | 20 | target/jsw/waf 21 | /logs 22 | 23 | **/* 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /doc/args.txt: -------------------------------------------------------------------------------- 1 | \.\./ 2 | \:\$ 3 | \$\{ 4 | select.+(from|limit) 5 | (?:(union(.*?)select)) 6 | having|rongjitest 7 | sleep\((\s*)(\d*)(\s*)\) 8 | benchmark\((.*)\,(.*)\) 9 | base64_decode\( 10 | (?:from\W+information_schema\W) 11 | (?:(?:current_)user|database|schema|connection_id)\s*\( 12 | (?:etc\/\W*passwd) 13 | into(\s+)+(?:dump|out)file\s* 14 | group\s+by.+\( 15 | xwork.methodaccessor 16 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 17 | xwork\.MethodAccessor 18 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 19 | java\.lang 20 | \$_(get|post|cookie|files|session|env|phplib|globals|server)\[ 21 | \<(iframe|script|body|img|layer|div|meta|style|base|object|input) 22 | (onmouseover|onerror|onload)\= 23 | -------------------------------------------------------------------------------- /doc/cookie.txt: -------------------------------------------------------------------------------- 1 | \.\./ 2 | \:\$ 3 | \$\{ 4 | select.+(from|limit) 5 | (?:(union(.*?)select)) 6 | having|rongjitest 7 | sleep\((\s*)(\d*)(\s*)\) 8 | benchmark\((.*)\,(.*)\) 9 | base64_decode\( 10 | (?:from\W+information_schema\W) 11 | (?:(?:current_)user|database|schema|connection_id)\s*\( 12 | (?:etc\/\W*passwd) 13 | into(\s+)+(?:dump|out)file\s* 14 | group\s+by.+\( 15 | xwork.methodaccessor 16 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 17 | xwork\.methodaccessor 18 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 19 | java\.lang 20 | \$_(get|post|cookie|files|session|env|phplib|globals|server)\[ 21 | -------------------------------------------------------------------------------- /doc/file.txt: -------------------------------------------------------------------------------- 1 | ^(php|jsp|asp)$ -------------------------------------------------------------------------------- /doc/framegraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdedeng/waf/9ba9a18857154830a35e3b10d111d025208f73ef/doc/framegraph.png -------------------------------------------------------------------------------- /doc/ip.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdedeng/waf/9ba9a18857154830a35e3b10d111d025208f73ef/doc/ip.txt -------------------------------------------------------------------------------- /doc/post.txt: -------------------------------------------------------------------------------- 1 | select.+(from|limit) 2 | (?:(union(.*?)select)) 3 | having|rongjitest 4 | sleep\((\s*)(\d*)(\s*)\) 5 | benchmark\((.*)\,(.*)\) 6 | base64_decode\( 7 | (?:from\W+information_schema\W) 8 | (?:(?:current_)user|database|schema|connection_id)\s*\( 9 | (?:etc\/\W*passwd) 10 | into(\s+)+(?:dump|out)file\s* 11 | group\s+by.+\( 12 | xwork.methodaccessor 13 | (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( 14 | xwork\.methodaccessor 15 | (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ 16 | java\.lang 17 | \$_(get|post|cookie|files|session|env|phplib|globals|server)\[ 18 | \<(iframe|script|body|img|layer|div|meta|style|base|object|input) 19 | (onmouseover|onerror|onload)\= 20 | -------------------------------------------------------------------------------- /doc/ua.txt: -------------------------------------------------------------------------------- 1 | (HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/) -------------------------------------------------------------------------------- /doc/url.txt: -------------------------------------------------------------------------------- 1 | \.(svn|git|htaccess|bash_history) 2 | \.(bak|inc|old|mdb|sql|backup|java|class)$ 3 | (vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar 4 | (phpmyadmin|jmx-console|jmxinvokerservlet) 5 | java\.lang 6 | /(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp) 7 | -------------------------------------------------------------------------------- /doc/wip.txt: -------------------------------------------------------------------------------- 1 | 192.168.227.30 -------------------------------------------------------------------------------- /doc/wurl.txt: -------------------------------------------------------------------------------- 1 | /favicon.ico$ 2 | -------------------------------------------------------------------------------- /src/main/groovy/info/yangguo/waf/script/GroovySandbox.groovy: -------------------------------------------------------------------------------- 1 | package info.yangguo.waf.script 2 | 3 | import io.netty.handler.codec.http.HttpObject 4 | import io.netty.handler.codec.http.HttpRequest 5 | import org.kohsuke.groovy.sandbox.GroovyValueFilter 6 | import org.slf4j.Logger 7 | 8 | import java.util.concurrent.atomic.AtomicBoolean 9 | 10 | /** 11 | * This {@link org.kohsuke.groovy.sandbox.GroovyInterceptor} implements a security check. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | class GroovySandbox extends GroovyValueFilter { 16 | @Override 17 | Object filter(Object o) { 18 | if (o == null || ALLOWED_TYPES.contains(o.class)) 19 | return o; 20 | if (o instanceof Script || o instanceof Closure) 21 | return o; // access to properties of compiled groovy script 22 | throw new SecurityException("Oops, unexpected type: " + o.class); 23 | } 24 | 25 | private static final Set ALLOWED_TYPES = [ 26 | Logger, 27 | String, 28 | Integer, 29 | Boolean, 30 | Long, 31 | Integer, 32 | Map, 33 | Set, 34 | HttpRequest, 35 | HttpObject, 36 | AtomicBoolean 37 | // all the primitive types should be OK, but I'm too lazy 38 | 39 | // I'm not adding Class, which rules out all the static method calls 40 | ] as Set 41 | } 42 | -------------------------------------------------------------------------------- /src/main/groovy/info/yangguo/waf/script/ScriptEntry.groovy: -------------------------------------------------------------------------------- 1 | package info.yangguo.waf.script 2 | 3 | import io.netty.handler.codec.http.HttpObject 4 | import io.netty.handler.codec.http.HttpRequest 5 | import org.codehaus.groovy.control.CompilerConfiguration 6 | import org.kohsuke.groovy.sandbox.SandboxTransformer 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory 9 | 10 | import java.util.concurrent.atomic.AtomicBoolean 11 | 12 | /** 13 | * @author guo.yang 14 | */ 15 | class ScriptEntry { 16 | static Logger logger = LoggerFactory.getLogger(ScriptEntry.class) 17 | 18 | void execute(HttpRequest originalRequest, HttpObject httpObject, AtomicBoolean result, String script) { 19 | GroovySandbox sandbox = new GroovySandbox() 20 | def cc = new CompilerConfiguration() 21 | cc.addCompilationCustomizers(new SandboxTransformer()) 22 | def binding = new Binding() 23 | binding.originalRequest = originalRequest 24 | binding.httpObject = httpObject 25 | binding.result = result 26 | GroovyShell sh = new GroovyShell(binding, cc) 27 | sandbox.register() 28 | try { 29 | sh.evaluate(script) 30 | } catch (SecurityException e) { 31 | logger.warn("Script execute exception\n-----------------------------------------------\n{}\n-----------------------------------------------", script, e) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/Constant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf; 17 | 18 | import com.codahale.metrics.MetricRegistry; 19 | import com.google.common.collect.Lists; 20 | import info.yangguo.waf.util.PropertiesUtil; 21 | import io.netty.channel.ChannelHandlerContext; 22 | import io.netty.handler.codec.http.HttpMessage; 23 | import io.netty.handler.codec.http.HttpRequest; 24 | 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | /** 29 | * @author:杨果 30 | * @date:2017/4/11 下午1:52 31 | *

32 | * Description: 33 | */ 34 | public class Constant { 35 | enum X_Frame_Options { 36 | DENY,//表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许. 37 | SAMEORIGIN//表示该页面可以在相同域名页面的 frame 中展示. 38 | } 39 | 40 | public static final MetricRegistry metrics = new MetricRegistry(); 41 | public static Map wafWebConfs = PropertiesUtil.getProperty("application.properties"); 42 | public static Map wafConfs = PropertiesUtil.getProperty("waf.properties"); 43 | public static int AcceptorThreads = Integer.parseInt(wafConfs.get("waf.acceptorThreads")); 44 | public static int ClientToProxyWorkerThreads = Integer.parseInt(wafConfs.get("waf.clientToProxyWorkerThreads")); 45 | public static int ProxyToServerWorkerThreads = Integer.parseInt(wafConfs.get("waf.proxyToServerWorkerThreads")); 46 | public static int ServerPort = Integer.parseInt(wafConfs.get("waf.serverPort")); 47 | public static int IdleConnectionTimeout = Integer.valueOf(wafConfs.get("waf.idleConnectionTimeout")); 48 | public final static X_Frame_Options X_Frame_Option = X_Frame_Options.SAMEORIGIN; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/HostResolverImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf; 17 | 18 | import info.yangguo.waf.config.ContextHolder; 19 | import info.yangguo.waf.model.ServerConfig; 20 | import org.littleshoot.proxy.HostResolver; 21 | 22 | import java.net.InetSocketAddress; 23 | import java.net.UnknownHostException; 24 | 25 | 26 | /** 27 | * @author:杨果 28 | * @date:2017/3/31 下午7:28 29 | *

30 | * Description: 31 | */ 32 | class HostResolverImpl implements HostResolver { 33 | @Override 34 | public InetSocketAddress resolve(String host, int port) 35 | throws UnknownHostException { 36 | String key; 37 | if (port == 80) 38 | key = host; 39 | else 40 | key = host + ":" + port; 41 | if (ContextHolder.getClusterService().getUpstreamConfig().containsKey(key)) { 42 | ServerConfig serverConfig = ContextHolder.getClusterService().getUpstreamConfig().get(key).getServer(); 43 | if (serverConfig != null) { 44 | return new InetSocketAddress(serverConfig.getIp(), serverConfig.getPort()); 45 | } else { 46 | throw new UnknownHostException(key + " have not healthy serverConfig."); 47 | } 48 | } else { 49 | throw new UnknownHostException(key); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/WafHttpHeaderNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf; 17 | 18 | import io.netty.util.AsciiString; 19 | 20 | public class WafHttpHeaderNames { 21 | public static final AsciiString X_REAL_IP = AsciiString.cached("x-real-ip"); 22 | public static final AsciiString X_WAF_ROUTE = AsciiString.cached("x-waf-route"); 23 | public static final AsciiString X_FORWARDED_FOR = AsciiString.cached("X-Forwarded-For"); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/AdminProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import lombok.Data; 19 | import org.springframework.beans.factory.annotation.Value; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.context.annotation.PropertySource; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Configuration 25 | @PropertySource("classpath:admin.properties") 26 | @Data 27 | @Component("adminProperties") 28 | public class AdminProperties { 29 | @Value("${email}") 30 | public String email; 31 | @Value("${password}") 32 | public String password; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/ClusterProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import lombok.Data; 19 | import org.springframework.boot.context.properties.ConfigurationProperties; 20 | import org.springframework.context.annotation.PropertySource; 21 | import org.springframework.stereotype.Component; 22 | 23 | import java.util.List; 24 | 25 | @Component("clusterProperties") 26 | @PropertySource("classpath:cluster.properties") 27 | @ConfigurationProperties(prefix = "waf") 28 | @Data 29 | public class ClusterProperties { 30 | private AtomixProperty atomix; 31 | private ZkProperty zk; 32 | 33 | @Data 34 | public static class AtomixProperty { 35 | private String id; 36 | private String metadataDir; 37 | private List node; 38 | 39 | } 40 | 41 | @Data 42 | public static class ZkProperty { 43 | private String connectionString; 44 | } 45 | 46 | @Data 47 | public static class ClusterNode { 48 | private String id; 49 | private String ip; 50 | private int socket_port; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/ContextHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import info.yangguo.waf.service.ClusterService; 19 | import org.springframework.beans.BeansException; 20 | import org.springframework.context.ApplicationContext; 21 | import org.springframework.context.ApplicationContextAware; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Component 25 | public class ContextHolder implements ApplicationContextAware { 26 | public static ApplicationContext applicationContext; 27 | private static ClusterService clusterService; 28 | 29 | @Override 30 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 31 | this.applicationContext = applicationContext; 32 | } 33 | 34 | public static ClusterService getClusterService() { 35 | return clusterService; 36 | } 37 | 38 | public static void setClusterService(ClusterService clusterService) { 39 | ContextHolder.clusterService = clusterService; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/CustomErrorController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import info.yangguo.waf.dto.ResultDto; 19 | import org.springframework.beans.factory.annotation.Value; 20 | import org.springframework.boot.autoconfigure.web.ErrorController; 21 | import org.springframework.http.HttpStatus; 22 | import org.springframework.http.ResponseEntity; 23 | import org.springframework.stereotype.Controller; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.ResponseBody; 26 | 27 | import javax.servlet.http.HttpServletRequest; 28 | 29 | @Controller 30 | @RequestMapping("${error.path:/error}") 31 | public class CustomErrorController implements ErrorController { 32 | 33 | @Value("${error.path:/error}") 34 | private String errorPath; 35 | 36 | @Override 37 | public String getErrorPath() { 38 | return this.errorPath; 39 | } 40 | 41 | @RequestMapping 42 | @ResponseBody 43 | public ResponseEntity error(HttpServletRequest request) { 44 | ResultDto resultDto = new ResultDto(); 45 | HttpStatus status = getStatus(request); 46 | resultDto.setCode(status.value()); 47 | resultDto.setValue(status.getReasonPhrase()); 48 | return new ResponseEntity(resultDto, HttpStatus.OK); 49 | } 50 | 51 | private HttpStatus getStatus(HttpServletRequest request) { 52 | Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); 53 | if (statusCode == null) { 54 | return HttpStatus.INTERNAL_SERVER_ERROR; 55 | } 56 | return HttpStatus.valueOf(statusCode); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/ExceptionHandlerAdvice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import com.google.common.collect.Maps; 19 | import info.yangguo.waf.dto.ResultDto; 20 | import info.yangguo.waf.exception.UnauthorizedException; 21 | import info.yangguo.waf.util.JsonUtil; 22 | import org.apache.commons.lang.exception.ExceptionUtils; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.http.HttpStatus; 26 | import org.springframework.http.converter.HttpMessageNotReadableException; 27 | import org.springframework.validation.FieldError; 28 | import org.springframework.validation.ObjectError; 29 | import org.springframework.web.bind.MethodArgumentNotValidException; 30 | import org.springframework.web.bind.ServletRequestBindingException; 31 | import org.springframework.web.bind.annotation.ControllerAdvice; 32 | import org.springframework.web.bind.annotation.ExceptionHandler; 33 | import org.springframework.web.bind.annotation.ResponseBody; 34 | import org.springframework.web.cors.CorsUtils; 35 | 36 | import javax.servlet.http.HttpServletRequest; 37 | import javax.servlet.http.HttpServletResponse; 38 | import java.util.Enumeration; 39 | import java.util.List; 40 | import java.util.Map; 41 | 42 | @ControllerAdvice 43 | @ResponseBody 44 | public class ExceptionHandlerAdvice { 45 | private final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlerAdvice.class); 46 | 47 | @ExceptionHandler(HttpMessageNotReadableException.class) 48 | public ResultDto handleHttpMessageNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request, HttpServletResponse response) { 49 | LOGGER.warn(ExceptionUtils.getFullStackTrace(e)); 50 | addCorsHeader(request, response); 51 | ResultDto resultDto = new ResultDto(); 52 | resultDto.setCode(HttpStatus.BAD_REQUEST.value()); 53 | resultDto.setValue("数据格式错误"); 54 | return resultDto; 55 | } 56 | 57 | 58 | @ExceptionHandler(MethodArgumentNotValidException.class) 59 | public ResultDto handleArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request, HttpServletResponse response) { 60 | LOGGER.warn(ExceptionUtils.getFullStackTrace(e)); 61 | addCorsHeader(request, response); 62 | List errorList = e.getBindingResult().getAllErrors(); 63 | Map errMap = Maps.newHashMap(); 64 | for (ObjectError err : errorList) { 65 | if (err instanceof FieldError) 66 | errMap.put(((FieldError) err).getField(), err.getDefaultMessage()); 67 | else if (err instanceof ObjectError) 68 | errMap.put(((ObjectError) err).getObjectName(), err.getDefaultMessage()); 69 | } 70 | ResultDto resultDto = new ResultDto(); 71 | resultDto.setCode(HttpStatus.BAD_REQUEST.value()); 72 | resultDto.setValue(JsonUtil.toJson(errMap, true)); 73 | 74 | return resultDto; 75 | } 76 | 77 | 78 | @ExceptionHandler(ServletRequestBindingException.class) 79 | public ResultDto handleServletRequestBindingException(ServletRequestBindingException e, HttpServletRequest request, HttpServletResponse response) { 80 | LOGGER.error(ExceptionUtils.getFullStackTrace(e)); 81 | addCorsHeader(request, response); 82 | ResultDto resultDto = new ResultDto(); 83 | resultDto.setCode(HttpStatus.BAD_REQUEST.value()); 84 | resultDto.setValue("Header/Body不正确"); 85 | return resultDto; 86 | } 87 | 88 | @ExceptionHandler(UnauthorizedException.class) 89 | public ResultDto handleServletRequestUnauthorizedException(UnauthorizedException e, HttpServletRequest request, HttpServletResponse response) { 90 | addCorsHeader(request, response); 91 | ResultDto resultDto = new ResultDto(); 92 | resultDto.setCode(HttpStatus.UNAUTHORIZED.value()); 93 | resultDto.setValue("请登录"); 94 | return resultDto; 95 | } 96 | 97 | private void addCorsHeader(HttpServletRequest request, HttpServletResponse response) { 98 | if (CorsUtils.isCorsRequest(request)) { 99 | Enumeration headers = request.getHeaderNames(); 100 | String origin = null; 101 | while (headers.hasMoreElements()) { 102 | String header = headers.nextElement(); 103 | if (header.toLowerCase().equals("origin")) { 104 | origin = request.getHeader(header); 105 | } 106 | } 107 | response.setHeader("Access-Control-Allow-Origin", origin); 108 | response.setHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS"); 109 | response.setHeader("Access-Control-Allow-Credentials", "true"); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/LoginInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import info.yangguo.waf.exception.UnauthorizedException; 19 | import info.yangguo.waf.service.JwtTokenService; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.http.HttpMethod; 22 | import org.springframework.stereotype.Component; 23 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 24 | 25 | import javax.servlet.http.Cookie; 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | 29 | @Component 30 | public class LoginInterceptor extends HandlerInterceptorAdapter { 31 | @Autowired 32 | private JwtTokenService jwtTokenService; 33 | 34 | @Override 35 | public boolean preHandle(HttpServletRequest request, 36 | HttpServletResponse response, Object object) throws UnauthorizedException { 37 | Cookie[] cookies = request.getCookies(); 38 | if (cookies != null) { 39 | for (Cookie cookie : cookies) { 40 | if ("WAFTOKEN".equals(cookie.getName())) { 41 | if (jwtTokenService.verifyToken(cookie.getValue())) { 42 | return true; 43 | } else { 44 | throw new UnauthorizedException(); 45 | } 46 | } 47 | } 48 | } else if (HttpMethod.OPTIONS.name().equals(request.getMethod())) { 49 | return true; 50 | } 51 | throw new UnauthorizedException(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.config; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; 22 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 23 | import org.springframework.web.filter.CharacterEncodingFilter; 24 | import org.springframework.web.multipart.support.StandardServletMultipartResolver; 25 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 26 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 27 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 28 | import springfox.documentation.builders.ApiInfoBuilder; 29 | import springfox.documentation.builders.PathSelectors; 30 | import springfox.documentation.builders.RequestHandlerSelectors; 31 | import springfox.documentation.service.ApiInfo; 32 | import springfox.documentation.spi.DocumentationType; 33 | import springfox.documentation.spring.web.plugins.Docket; 34 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 35 | 36 | import javax.servlet.Filter; 37 | 38 | @Configuration 39 | @EnableSwagger2 40 | public class WebConfig extends WebMvcConfigurerAdapter { 41 | @Autowired 42 | private LoginInterceptor loginInterceptor; 43 | 44 | @Override 45 | public void addCorsMappings(CorsRegistry registry) { 46 | registry.addMapping("/**") 47 | .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS"); 48 | } 49 | 50 | @Bean 51 | public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { 52 | return new PropertySourcesPlaceholderConfigurer(); 53 | } 54 | 55 | @Bean 56 | public Filter characterEncodingFilter() { 57 | CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); 58 | characterEncodingFilter.setEncoding("UTF-8"); 59 | characterEncodingFilter.setForceEncoding(true); 60 | return characterEncodingFilter; 61 | } 62 | 63 | @Bean 64 | public MappingJackson2HttpMessageConverter converter() { 65 | MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 66 | return converter; 67 | } 68 | 69 | @Bean 70 | public StandardServletMultipartResolver getStandardServletMultipartResolver() { 71 | return new StandardServletMultipartResolver(); 72 | } 73 | 74 | @Bean 75 | public Docket api() { 76 | return new Docket(DocumentationType.SWAGGER_2) 77 | .select() 78 | .apis(RequestHandlerSelectors.any()) 79 | .paths(PathSelectors.regex("/api/.*"))//此处配置需注意,需要暴露什么配置什么 80 | .build() 81 | .apiInfo(apiInfo()); 82 | } 83 | 84 | private ApiInfo apiInfo() { 85 | return new ApiInfoBuilder() 86 | .title("TITLE") 87 | .description("DESCRIPTION") 88 | .version("VERSION") 89 | .termsOfServiceUrl("https://github.com/chengdedeng/waf") 90 | .license("Apache License 2.0") 91 | .licenseUrl("https://en.wikipedia.org/wiki/Apache_License") 92 | .build(); 93 | } 94 | 95 | @Override 96 | public void addInterceptors(InterceptorRegistry registry) { 97 | registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**").excludePathPatterns("/api/user/**"); 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/controller/UserController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.controller; 17 | 18 | import info.yangguo.waf.config.AdminProperties; 19 | import info.yangguo.waf.dto.ResultDto; 20 | import info.yangguo.waf.dto.UserDto; 21 | import info.yangguo.waf.service.JwtTokenService; 22 | import io.swagger.annotations.Api; 23 | import io.swagger.annotations.ApiOperation; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.http.HttpStatus; 26 | import org.springframework.validation.annotation.Validated; 27 | import org.springframework.web.bind.annotation.*; 28 | 29 | import javax.servlet.http.HttpServletResponse; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | @RestController 34 | @RequestMapping(value = "api/user") 35 | @Api(value = "api/user", description = "用户相关的接口") 36 | public class UserController { 37 | @Autowired 38 | private AdminProperties adminProperties; 39 | @Autowired 40 | private JwtTokenService jwtTokenService; 41 | 42 | @ApiOperation(value = "登录") 43 | @ResponseBody 44 | @PostMapping(value = "login") 45 | public ResultDto login(HttpServletResponse response, @RequestBody @Validated UserDto userDto) { 46 | ResultDto resultDto = new ResultDto(); 47 | if (adminProperties.email.equals(userDto.getEmail()) && adminProperties.password.equals(userDto.getPassword())) { 48 | resultDto.setCode(HttpStatus.OK.value()); 49 | } else { 50 | resultDto.setCode(HttpStatus.FORBIDDEN.value()); 51 | } 52 | Map claims = new HashMap<>(); 53 | claims.put("email", userDto.getEmail()); 54 | String token = jwtTokenService.genToken(claims); 55 | response.setHeader("Set-Cookie", "WAFTOKEN=" + token + "; Path=/"); 56 | return resultDto; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/ForwardConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import io.swagger.annotations.ApiModelProperty; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | import org.hibernate.validator.constraints.NotEmpty; 24 | 25 | import javax.validation.constraints.NotNull; 26 | 27 | @Data 28 | @Builder 29 | @AllArgsConstructor 30 | @NoArgsConstructor 31 | public class ForwardConfigDto { 32 | @NotEmpty 33 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 34 | private String wafRoute; 35 | @NotNull 36 | @ApiModelProperty(value = "是否开启,true启用,false关闭。") 37 | private Boolean isStart; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/ForwardConfigItemDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.model.ForwardType; 19 | import info.yangguo.waf.validator.Exist; 20 | import info.yangguo.waf.validator.NotExist; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import lombok.NoArgsConstructor; 26 | import org.hibernate.validator.constraints.NotEmpty; 27 | 28 | import javax.validation.constraints.NotNull; 29 | import javax.validation.constraints.Null; 30 | 31 | @Data 32 | @Builder 33 | @AllArgsConstructor 34 | @NoArgsConstructor 35 | public class ForwardConfigItemDto { 36 | @NotEmpty 37 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 38 | private String wafRoute; 39 | @NotEmpty 40 | @ApiModelProperty(value = "配置项名称。", required = true) 41 | private String name; 42 | @NotNull(groups = Exist.class) 43 | @Null(groups = NotExist.class) 44 | @ApiModelProperty(value = "是否开启,true启用,false关闭。") 45 | private Boolean isStart; 46 | @Null(groups = NotExist.class) 47 | @ApiModelProperty(value = "item扩展信息,目前只在CCSecurityFilter有使用。") 48 | private ForwardType type; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/RedirectConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.validator.CheckRedirectConfigItem; 19 | import info.yangguo.waf.validator.Exist; 20 | import info.yangguo.waf.validator.NotExist; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import lombok.NoArgsConstructor; 26 | import org.hibernate.validator.constraints.NotEmpty; 27 | 28 | import javax.validation.constraints.NotNull; 29 | import javax.validation.constraints.Null; 30 | import java.util.List; 31 | 32 | @Data 33 | @Builder 34 | @AllArgsConstructor 35 | @NoArgsConstructor 36 | @CheckRedirectConfigItem(groups = Exist.class) 37 | public class RedirectConfigDto { 38 | @NotEmpty 39 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 40 | private String wafRoute; 41 | @NotNull(groups = Exist.class) 42 | @Null(groups = NotExist.class) 43 | @ApiModelProperty(value = "开关,true启用,false关闭。") 44 | private Boolean isStart; 45 | @NotNull(groups = Exist.class) 46 | @Null(groups = NotExist.class) 47 | private List items; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/ResponseConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import io.swagger.annotations.ApiModelProperty; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | import org.hibernate.validator.constraints.NotEmpty; 24 | 25 | import javax.validation.constraints.NotNull; 26 | import javax.validation.constraints.Pattern; 27 | 28 | @Data 29 | @Builder 30 | @AllArgsConstructor 31 | @NoArgsConstructor 32 | public class ResponseConfigDto { 33 | @NotEmpty 34 | @Pattern(regexp = "info\\.yangguo\\.waf\\.response\\..*ResponseProcess") 35 | @ApiModelProperty(value = "response拦截器名称。", required = true) 36 | private String filterName; 37 | @NotNull 38 | @ApiModelProperty(value = "是否开启,true启用,false关闭。") 39 | private Boolean isStart; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/ResultDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Builder; 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | 26 | @Data 27 | @Builder 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | @ApiModel("响应结果") 31 | @JsonInclude(JsonInclude.Include.NON_NULL) 32 | public class ResultDto { 33 | @ApiModelProperty(value = "结果代码。") 34 | private int code; 35 | @ApiModelProperty(value = "结果对象。") 36 | private T value; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/RewriteConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.validator.CheckRewriteConfigItem; 19 | import info.yangguo.waf.validator.Exist; 20 | import info.yangguo.waf.validator.NotExist; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import lombok.NoArgsConstructor; 26 | import org.hibernate.validator.constraints.NotEmpty; 27 | 28 | import javax.validation.constraints.NotNull; 29 | import javax.validation.constraints.Null; 30 | import java.util.List; 31 | 32 | @Data 33 | @Builder 34 | @AllArgsConstructor 35 | @NoArgsConstructor 36 | @CheckRewriteConfigItem(groups = Exist.class) 37 | public class RewriteConfigDto { 38 | @NotEmpty 39 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 40 | private String wafRoute; 41 | @NotNull(groups = Exist.class) 42 | @Null(groups = NotExist.class) 43 | @ApiModelProperty(value = "开关,true启用,false关闭。") 44 | private Boolean isStart; 45 | @NotNull(groups = Exist.class) 46 | @Null(groups = NotExist.class) 47 | private List items; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/SecurityConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import io.swagger.annotations.ApiModelProperty; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | import org.hibernate.validator.constraints.NotEmpty; 24 | 25 | import javax.validation.constraints.NotNull; 26 | import javax.validation.constraints.Pattern; 27 | 28 | @Data 29 | @Builder 30 | @AllArgsConstructor 31 | @NoArgsConstructor 32 | public class SecurityConfigDto { 33 | @NotEmpty 34 | @Pattern(regexp = "info\\.yangguo\\.waf\\.request\\.security\\..*Security") 35 | @ApiModelProperty(value = "security拦截器名称。", required = true) 36 | private String filterName; 37 | @NotNull 38 | @ApiModelProperty(value = "是否开启,true启用,false关闭。") 39 | private Boolean isStart; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/SecurityConfigItemDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.validator.CheckSecurityConfigItem; 19 | import info.yangguo.waf.validator.Exist; 20 | import info.yangguo.waf.validator.NotExist; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import lombok.NoArgsConstructor; 26 | import org.hibernate.validator.constraints.NotEmpty; 27 | 28 | import javax.validation.constraints.NotNull; 29 | import javax.validation.constraints.Null; 30 | import javax.validation.constraints.Pattern; 31 | import java.util.Map; 32 | 33 | @Data 34 | @Builder 35 | @AllArgsConstructor 36 | @NoArgsConstructor 37 | @CheckSecurityConfigItem(groups = Exist.class) 38 | public class SecurityConfigItemDto { 39 | @NotEmpty 40 | @Pattern(regexp = "info\\.yangguo\\.waf\\.request\\.security\\..*Security") 41 | @ApiModelProperty(value = "security拦截器名称。", required = true) 42 | private String filterName; 43 | @NotEmpty 44 | @ApiModelProperty(value = "配置项名称。", required = true) 45 | private String name; 46 | @NotNull(groups = Exist.class) 47 | @Null(groups = NotExist.class) 48 | @ApiModelProperty(value = "是否开启,true启用,false关闭。") 49 | private Boolean isStart; 50 | @Null(groups = NotExist.class) 51 | @ApiModelProperty(value = "item扩展信息,目前只在CCSecurityFilter有使用。") 52 | private Map extension; 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/UpstreamConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.validator.Exist; 19 | import info.yangguo.waf.validator.NotExist; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Builder; 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | import org.hibernate.validator.constraints.NotEmpty; 26 | 27 | import javax.validation.constraints.NotNull; 28 | import javax.validation.constraints.Null; 29 | 30 | @Data 31 | @Builder 32 | @AllArgsConstructor 33 | @NoArgsConstructor 34 | public class UpstreamConfigDto { 35 | @NotEmpty 36 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 37 | private String wafRoute; 38 | @NotNull(groups = Exist.class) 39 | @Null(groups = NotExist.class) 40 | @ApiModelProperty(value = "开关,true启用,false关闭。") 41 | private Boolean isStart; 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/UpstreamServerConfigDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import info.yangguo.waf.validator.Exist; 19 | import info.yangguo.waf.validator.NotExist; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Builder; 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | import org.hibernate.validator.constraints.NotEmpty; 26 | 27 | import javax.validation.constraints.*; 28 | 29 | @Data 30 | @Builder 31 | @AllArgsConstructor 32 | @NoArgsConstructor 33 | public class UpstreamServerConfigDto { 34 | @NotEmpty 35 | @ApiModelProperty(value = "x-waf-route,路由标志。", required = true) 36 | private String wafRoute; 37 | @NotEmpty 38 | @ApiModelProperty(value = "ip地址。", required = true) 39 | @Pattern(regexp = "(^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$)|(^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$)") 40 | private String ip; 41 | @Min(1) 42 | @Max(65535) 43 | @NotNull 44 | @ApiModelProperty(value = "端口。", required = true) 45 | private Integer port; 46 | @NotNull(groups = Exist.class) 47 | @Null(groups = NotExist.class) 48 | @ApiModelProperty(value = "开关,true启用,false关闭。") 49 | private Boolean isStart; 50 | @Min(value = 1, groups = Exist.class) 51 | @NotNull(groups = Exist.class) 52 | @Null(groups = NotExist.class) 53 | @ApiModelProperty("权重。") 54 | private Integer weight; 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.dto; 17 | 18 | import io.swagger.annotations.ApiModelProperty; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | import org.hibernate.validator.constraints.Email; 24 | 25 | import javax.validation.constraints.NotNull; 26 | 27 | @Data 28 | @Builder 29 | @AllArgsConstructor 30 | @NoArgsConstructor 31 | public class UserDto { 32 | @NotNull 33 | @Email 34 | @ApiModelProperty(value = "邮箱。", required = true) 35 | private String email; 36 | @NotNull 37 | @ApiModelProperty(value = "密码。", required = true) 38 | private String password; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/exception/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.exception; 17 | 18 | public class UnauthorizedException extends Exception { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/BasicConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | 23 | import java.io.Serializable; 24 | import java.util.Map; 25 | 26 | @Data 27 | @AllArgsConstructor 28 | @JsonInclude(JsonInclude.Include.NON_NULL) 29 | public class BasicConfig extends Config implements Serializable { 30 | private static final long serialVersionUID = 666558172889943990L; 31 | 32 | @Builder 33 | public BasicConfig(Boolean isStart, Map extension) { 34 | super(isStart, extension); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import lombok.AllArgsConstructor; 19 | import lombok.Data; 20 | import lombok.NoArgsConstructor; 21 | 22 | import java.io.Serializable; 23 | import java.util.Map; 24 | 25 | @Data 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public abstract class Config implements Serializable { 29 | private static final long serialVersionUID = 5343330681233227162L; 30 | /** 31 | * 开关,ture开启,false关闭 32 | */ 33 | private Boolean isStart; 34 | /** 35 | * 自定义扩展信息 36 | */ 37 | private Map extension; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ForwardConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | import java.util.List; 26 | 27 | @Data 28 | @Builder 29 | @AllArgsConstructor 30 | @NoArgsConstructor 31 | @JsonInclude(JsonInclude.Include.NON_NULL) 32 | public class ForwardConfig implements Serializable { 33 | private static final long serialVersionUID = -2551198849518304264L; 34 | /** 35 | * 路由标志 36 | */ 37 | private String wafRoute; 38 | /** 39 | * 配置信息 40 | */ 41 | private BasicConfig config; 42 | /** 43 | * 配置项 44 | */ 45 | private List forwardConfigItems; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ForwardConfigItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | public class ForwardConfigItem implements Serializable { 32 | private static final long serialVersionUID = -8055712788556691003L; 33 | /** 34 | * 名称 35 | */ 36 | private String name; 37 | /** 38 | * 配置信息 39 | */ 40 | private BasicConfig config; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ForwardType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | public enum ForwardType { 19 | HTTP, 20 | DUBBO, 21 | GRPC, 22 | THRIFT, 23 | SOFA; 24 | 25 | public static ForwardType getType(String name) { 26 | for (ForwardType type : ForwardType.values()) { 27 | if (type.name().equals(name)) 28 | return type; 29 | } 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ResponseConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | public class ResponseConfig implements Serializable { 32 | private static final long serialVersionUID = 2031500986318114814L; 33 | /** 34 | * 拦截器名称 35 | */ 36 | private String filterName; 37 | /** 38 | * 配置信息 39 | */ 40 | private BasicConfig config; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | import java.util.List; 26 | 27 | 28 | @Data 29 | @Builder 30 | @AllArgsConstructor 31 | @NoArgsConstructor 32 | @JsonInclude(JsonInclude.Include.NON_NULL) 33 | public class SecurityConfig implements Serializable { 34 | private static final long serialVersionUID = 7698988201535399962L; 35 | /** 36 | * 拦截器名称 37 | */ 38 | private String filterName; 39 | /** 40 | * 配置信息 41 | */ 42 | private BasicConfig config; 43 | /** 44 | * 配置项 45 | */ 46 | private List securityConfigItems; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/SecurityConfigItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | public class SecurityConfigItem implements Serializable { 32 | private static final long serialVersionUID = 3823749021458846717L; 33 | /** 34 | * 名称 35 | */ 36 | private String name; 37 | /** 38 | * 配置信息 39 | */ 40 | private BasicConfig config; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ServerBasicConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | import java.util.Map; 26 | 27 | @Data 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | public class ServerBasicConfig extends Config implements Serializable { 32 | private static final long serialVersionUID = 9124790711127925033L; 33 | /** 34 | * 服务器权重 35 | */ 36 | private Integer weight; 37 | 38 | @Builder 39 | public ServerBasicConfig(Boolean isStart, Map extension, Integer weight) { 40 | super(isStart, extension); 41 | this.weight = weight; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/ServerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | @JsonInclude(JsonInclude.Include.NON_NULL) 31 | public class ServerConfig implements Serializable { 32 | private static final long serialVersionUID = 7426117635312217242L; 33 | /** 34 | * 服务器ip 35 | */ 36 | private String ip; 37 | /** 38 | * 服务器端口 39 | */ 40 | private Integer port; 41 | /** 42 | * 服务器配置信息 43 | */ 44 | public ServerBasicConfig config; 45 | /** 46 | * 健康标记 47 | */ 48 | private Boolean isHealth; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/UpstreamConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Builder; 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.io.Serializable; 25 | import java.util.List; 26 | 27 | @Data 28 | @Builder 29 | @AllArgsConstructor 30 | @NoArgsConstructor 31 | @JsonInclude(JsonInclude.Include.NON_NULL) 32 | public class UpstreamConfig implements Serializable { 33 | private static final long serialVersionUID = 1392103965835939457L; 34 | /** 35 | * upstream唯一标志 36 | */ 37 | private String wafRoute; 38 | /** 39 | * 配置信息 40 | */ 41 | private BasicConfig config; 42 | /** 43 | * 服务器列表 44 | */ 45 | private List serverConfigs; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/model/WeightedRoundRobinScheduling.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonIgnore; 19 | import lombok.Getter; 20 | import lombok.NoArgsConstructor; 21 | import lombok.Setter; 22 | 23 | import java.io.Serializable; 24 | import java.math.BigInteger; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.concurrent.CopyOnWriteArrayList; 29 | 30 | /** 31 | * @author:杨果 32 | * @date:2017/4/18 上午11:17 33 | *

34 | * Description: 35 | *

36 | * 权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 37 | */ 38 | @NoArgsConstructor 39 | public class WeightedRoundRobinScheduling implements Serializable { 40 | private static final long serialVersionUID = -3030570670940352661L; 41 | @Getter 42 | @Setter 43 | private BasicConfig basicConfig;//host对应的upstream是否开启 44 | private int currentIndex = -1;// 上一次选择的服务器 45 | private int currentWeight = 0;// 当前调度的权值 46 | @Getter 47 | private CopyOnWriteArrayList healthilyServerConfigs = new CopyOnWriteArrayList(); //健康服务器集合 48 | @Getter 49 | private CopyOnWriteArrayList unhealthilyServerConfigs = new CopyOnWriteArrayList<>(); //不健康服务器集合 50 | @Getter 51 | private Map serversMap = new HashMap<>(); 52 | 53 | /** 54 | * 返回最大公约数 55 | */ 56 | private int gcd(int a, int b) { 57 | BigInteger b1 = new BigInteger(String.valueOf(a)); 58 | BigInteger b2 = new BigInteger(String.valueOf(b)); 59 | BigInteger gcd = b1.gcd(b2); 60 | return gcd.intValue(); 61 | } 62 | 63 | 64 | /** 65 | * 返回所有服务器权重的最大公约数 66 | */ 67 | private int getGCDForServers(List serverConfigList) { 68 | int w = 0; 69 | for (int i = 0, len = serverConfigList.size(); i < len - 1; i++) { 70 | if (w == 0) { 71 | w = gcd(serverConfigList.get(i).config.getWeight(), serverConfigList.get(i + 1).getConfig().getWeight()); 72 | } else { 73 | w = gcd(w, serverConfigList.get(i + 1).getConfig().getWeight()); 74 | } 75 | } 76 | return w; 77 | } 78 | 79 | /** 80 | * 返回所有服务器中的最大权重 81 | */ 82 | private int getMaxWeightForServers(List serverConfigList) { 83 | int w = 0; 84 | for (int i = 0, len = serverConfigList.size(); i < len - 1; i++) { 85 | if (w == 0) { 86 | w = Math.max(serverConfigList.get(i).getConfig().getWeight(), serverConfigList.get(i + 1).getConfig().getWeight()); 87 | } else { 88 | w = Math.max(w, serverConfigList.get(i + 1).getConfig().getWeight()); 89 | } 90 | } 91 | return w; 92 | } 93 | 94 | /** 95 | * 算法流程: 假设有一组服务器 S = {S0, S1, …, Sn-1} 有相应的权重,变量currentIndex表示上次选择的服务器 96 | * 权值currentWeight初始化为0,currentIndex初始化为-1 ,当第一次的时候返回 权值取最大的那个服务器, 通过权重的不断递减 寻找 97 | * 适合的服务器返回,直到轮询结束,权值返回为0 98 | */ 99 | @JsonIgnore 100 | public ServerConfig getServer() { 101 | if (healthilyServerConfigs.size() == 0) { 102 | return null; 103 | } else if (healthilyServerConfigs.size() == 1) { 104 | return healthilyServerConfigs.get(0); 105 | } else { 106 | while (true) { 107 | currentIndex = (currentIndex + 1) % healthilyServerConfigs.size(); 108 | if (currentIndex == 0) { 109 | currentWeight = currentWeight - getGCDForServers(healthilyServerConfigs); 110 | if (currentWeight <= 0) { 111 | currentWeight = getMaxWeightForServers(healthilyServerConfigs); 112 | if (currentWeight == 0) 113 | return null; 114 | } 115 | } 116 | if (healthilyServerConfigs.get(currentIndex).getConfig().getWeight() >= currentWeight) { 117 | return healthilyServerConfigs.get(currentIndex); 118 | } 119 | } 120 | } 121 | } 122 | 123 | public WeightedRoundRobinScheduling(List serverConfigs, BasicConfig basicConfig) { 124 | this.basicConfig = basicConfig; 125 | if (basicConfig != null && basicConfig.getIsStart()) { 126 | serverConfigs.stream().forEach(server -> { 127 | if (server.getConfig().getIsStart()) 128 | healthilyServerConfigs.add(server); 129 | }); 130 | } 131 | serverConfigs.stream().forEach(server -> { 132 | serversMap.put(server.getIp() + "_" + server.getPort(), server); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/request/RedirectFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.request; 17 | 18 | import info.yangguo.waf.WafHttpHeaderNames; 19 | import info.yangguo.waf.config.ContextHolder; 20 | import info.yangguo.waf.model.BasicConfig; 21 | import info.yangguo.waf.util.ResponseUtil; 22 | import io.netty.handler.codec.http.*; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.web.util.UriUtils; 26 | 27 | import java.util.Map; 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | import static org.apache.commons.lang3.CharEncoding.UTF_8; 32 | 33 | public class RedirectFilter implements RequestFilter { 34 | private static Logger LOGGER = LoggerFactory.getLogger(RedirectFilter.class); 35 | 36 | @Override 37 | public HttpResponse doFilter(HttpRequest originalRequest, HttpObject httpObject) { 38 | HttpResponse httpResponse = null; 39 | if (httpObject instanceof HttpRequest) { 40 | String wafRoute = originalRequest.headers().getAsString(WafHttpHeaderNames.X_WAF_ROUTE); 41 | String redirectUri = originalRequest.uri(); 42 | try { 43 | redirectUri = UriUtils.decode(originalRequest.uri(), UTF_8); 44 | } catch (Exception e) { 45 | LOGGER.warn("uri decode is failed.", e); 46 | } 47 | 48 | Map redirectConfig = ContextHolder.getClusterService().getRedirectConfigs(); 49 | if (redirectConfig.containsKey(wafRoute) && redirectConfig.get(wafRoute).getIsStart()) { 50 | for (Map.Entry entry : redirectConfig.get(wafRoute).getExtension().entrySet()) { 51 | Pattern redirectPattern = Pattern.compile(entry.getKey()); 52 | Matcher redirectMatcher = redirectPattern.matcher(redirectUri); 53 | if (redirectMatcher.matches()) { 54 | String[] parts = ((String) entry.getValue()).split(" +"); 55 | HttpHeaders httpHeaders = new DefaultHttpHeaders(); 56 | httpHeaders.add(HttpHeaderNames.LOCATION, parts[0] + originalRequest.uri()); 57 | httpResponse = ResponseUtil.createResponse(HttpResponseStatus.valueOf(Integer.valueOf(parts[1])), originalRequest, httpHeaders); 58 | } 59 | } 60 | } 61 | } 62 | return httpResponse; 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/request/RequestFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.request; 17 | 18 | import io.netty.handler.codec.http.*; 19 | 20 | public interface RequestFilter { 21 | HttpResponse doFilter(HttpRequest originalRequest, HttpObject httpObject) throws Exception; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/request/RewriteFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.request; 17 | 18 | import com.google.common.collect.Lists; 19 | import info.yangguo.waf.WafHttpHeaderNames; 20 | import info.yangguo.waf.config.ContextHolder; 21 | import info.yangguo.waf.model.BasicConfig; 22 | import io.netty.handler.codec.http.HttpObject; 23 | import io.netty.handler.codec.http.HttpRequest; 24 | import io.netty.handler.codec.http.HttpResponse; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.springframework.web.util.UriUtils; 28 | 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Optional; 32 | import java.util.regex.Matcher; 33 | import java.util.regex.Pattern; 34 | 35 | import static org.apache.commons.lang3.CharEncoding.UTF_8; 36 | 37 | public class RewriteFilter implements RequestFilter { 38 | private static Logger LOGGER = LoggerFactory.getLogger(RewriteFilter.class); 39 | 40 | public HttpResponse doFilter(HttpRequest originalRequest, HttpObject httpObject) { 41 | if (httpObject instanceof HttpRequest) { 42 | String wafRoute = originalRequest.headers().getAsString(WafHttpHeaderNames.X_WAF_ROUTE); 43 | String oldUri = originalRequest.uri(); 44 | try { 45 | oldUri = UriUtils.decode(originalRequest.uri(), UTF_8); 46 | } catch (Exception e) { 47 | LOGGER.warn("uri decode is failed.", e); 48 | } 49 | 50 | 51 | Map rewriteConfig = ContextHolder.getClusterService().getRewriteConfigs(); 52 | if (rewriteConfig.containsKey(wafRoute) && rewriteConfig.get(wafRoute).getIsStart()) { 53 | String newUri = null; 54 | for (Map.Entry entry : rewriteConfig.get(wafRoute).getExtension().entrySet()) { 55 | Pattern oldUriPattern = Pattern.compile(entry.getKey()); 56 | Matcher oldUriMatcher = oldUriPattern.matcher(oldUri); 57 | if (oldUriMatcher.matches()) { 58 | //保存老URI中的匹配组信息,新URI中需要替换使用 59 | List oldUriGroups = Lists.newArrayList(); 60 | for (int i = 1; i < oldUriMatcher.groupCount() + 1; i++) { 61 | oldUriGroups.add(oldUriMatcher.group(i)); 62 | } 63 | //获取rewrite config信息 64 | newUri = (String) entry.getValue(); 65 | //老URI没有分组信息,意味着新URI就是目标URI,不需要替换 66 | if (oldUriGroups.size() > 0) { 67 | //获取newUrlRegex中的需要替换的记号 68 | List newUriGroup = Lists.newArrayList(); 69 | Pattern newUriPattern = Pattern.compile("(\\$\\d+)"); 70 | Matcher newUriMatcher = newUriPattern.matcher(newUri); 71 | while (newUriMatcher.find()) { 72 | newUriGroup.add(Integer.valueOf(newUriMatcher.group().replace("$", ""))); 73 | } 74 | //找出需要替换的最大值 75 | Optional max = newUriGroup.parallelStream().max(Integer::compareTo); 76 | if (max.isPresent() && max.get() <= oldUriGroups.size()) { 77 | for (Integer i : newUriGroup) { 78 | newUri = newUri.replaceAll("\\$" + i, oldUriGroups.get(i - 1)); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | if (newUri != null) { 85 | originalRequest.setUri(newUri); 86 | ((HttpRequest) httpObject).setUri(newUri); 87 | } 88 | } 89 | } 90 | return null; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/request/SecurityFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.request; 17 | 18 | import com.codahale.metrics.Timer; 19 | import info.yangguo.waf.Constant; 20 | import info.yangguo.waf.config.ContextHolder; 21 | import info.yangguo.waf.model.SecurityConfig; 22 | import info.yangguo.waf.request.security.*; 23 | import info.yangguo.waf.util.ResponseUtil; 24 | import io.netty.handler.codec.http.HttpObject; 25 | import io.netty.handler.codec.http.HttpRequest; 26 | import io.netty.handler.codec.http.HttpResponse; 27 | import io.netty.handler.codec.http.HttpResponseStatus; 28 | import org.apache.commons.lang3.tuple.ImmutablePair; 29 | import org.apache.commons.lang3.tuple.Pair; 30 | 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | /** 35 | * @author:杨果 36 | * @date:2017/4/11 上午11:32 37 | *

38 | * Description: 39 | *

40 | * 拦截器链 41 | */ 42 | public class SecurityFilter implements RequestFilter { 43 | public List filters = new ArrayList<>(); 44 | 45 | public SecurityFilter() { 46 | //要注意顺序,是从上向下执行的 47 | filters.add(new WIpSecurity()); 48 | filters.add(new IpSecurity()); 49 | filters.add(new CCSecurity()); 50 | filters.add(new ScannerSecurity()); 51 | filters.add(new WUrlSecurity()); 52 | filters.add(new UaSecurity()); 53 | filters.add(new UrlSecurity()); 54 | filters.add(new ArgsSecurity()); 55 | filters.add(new CookieSecurity()); 56 | filters.add(new PostSecurity()); 57 | filters.add(new FileSecurity()); 58 | filters.add(new ScriptSecurity()); 59 | } 60 | 61 | @Override 62 | public HttpResponse doFilter(HttpRequest originalRequest, HttpObject httpObject) { 63 | HttpResponse httpResponse = null; 64 | Pair pair = null; 65 | for (Security filter : filters) { 66 | Timer filterTimer = Constant.metrics.timer(filter.getClass().getName()); 67 | Timer.Context filterContext = filterTimer.time(); 68 | try { 69 | SecurityConfig config = ContextHolder.getClusterService().getSecurityConfigs().get(filter.getClass().getName()); 70 | if (config.getConfig().getIsStart()) { 71 | boolean result = filter.doFilter(originalRequest, httpObject, config.getSecurityConfigItems()); 72 | if (result && filter.isBlacklist()) { 73 | pair = new ImmutablePair<>(filter.isBlacklist(), filter); 74 | break; 75 | } else if (result && !filter.isBlacklist()) { 76 | break; 77 | } 78 | } 79 | } finally { 80 | filterContext.stop(); 81 | } 82 | } 83 | 84 | if (pair != null) { 85 | if (pair.getLeft()) { 86 | if (pair.getRight() instanceof CCSecurity) 87 | httpResponse = ResponseUtil.createResponse(HttpResponseStatus.SERVICE_UNAVAILABLE, originalRequest, null); 88 | else 89 | httpResponse = ResponseUtil.createResponse(HttpResponseStatus.FORBIDDEN, originalRequest, null); 90 | } 91 | } 92 | return httpResponse; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/info/yangguo/waf/request/security/ArgsSecurity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-present yangguo@outlook.com 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 | * http://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 | package info.yangguo.waf.request.security; 17 | 18 | import com.codahale.metrics.Timer; 19 | import info.yangguo.waf.Constant; 20 | import info.yangguo.waf.WafHttpHeaderNames; 21 | import info.yangguo.waf.model.SecurityConfigItem; 22 | import io.netty.handler.codec.http.HttpObject; 23 | import io.netty.handler.codec.http.HttpRequest; 24 | import org.apache.http.NameValuePair; 25 | import org.apache.http.client.utils.URLEncodedUtils; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | import java.util.List; 30 | import java.util.regex.Matcher; 31 | import java.util.regex.Pattern; 32 | 33 | import static io.netty.util.CharsetUtil.UTF_8; 34 | 35 | /** 36 | * @author:杨果 37 | * @date:2017/5/11 上午9:45 38 | *

39 | * Description: 40 | *

41 | * URL参数黑名单参数拦截 42 | *

43 | * 此处最好别用URI匹配正则,最好拆成NameValuePair一一匹配,这样精准一点。 44 | * 例如设置了一个