Skip to content

Commit fc1be1b

Browse files
committed
Add bean to parse safedomain
1 parent db6bff2 commit fc1be1b

14 files changed

+145
-83
lines changed

src/main/java/org/joychou/Application.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
99

1010

11+
1112
@ServletComponentScan // do filter
1213
@SpringBootApplication
1314
// @EnableEurekaClient // 测试Eureka请打开注释,防止控制台一直有warning

src/main/java/org/joychou/config/CustomCorsConfig.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ public WebMvcConfigurer corsConfigurer() {
2020
return new WebMvcConfigurerAdapter() {
2121
@Override
2222
public void addCorsMappings(CorsRegistry registry) {
23-
// 支持一级域名,因为重写了checkOrigin
24-
String[] allowOrigins = {"joychou.org", "http://test.joychou.me"};
23+
// 为了支持一级域名,重写了checkOrigin
24+
//String[] allowOrigins = {"joychou.org", "http://test.joychou.me"};
2525
registry.addMapping("/cors/sec/webMvcConfigurer") // /**表示所有路由path
26-
.allowedOrigins(allowOrigins)
26+
//.allowedOrigins(allowOrigins)
2727
.allowedMethods("GET", "POST")
2828
.allowCredentials(true);
2929
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.joychou.config;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
7+
8+
9+
/**
10+
* 为了不要每次调用都解析safedomain的xml,所以将解析动作放在bean里。
11+
*/
12+
@Configuration
13+
public class SafeDomainConfig {
14+
15+
private static final Logger LOGGER = LoggerFactory.getLogger(SafeDomainConfig.class);
16+
17+
@Bean
18+
public SafeDomainParser safeDomainParser() {
19+
try {
20+
LOGGER.info("SafeDomainParser bean inject successfully!!!");
21+
return new SafeDomainParser();
22+
} catch (Exception e) {
23+
LOGGER.error("SafeDomainParser is null " + e.getMessage(), e);
24+
}
25+
return null;
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.joychou.config;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.core.io.ClassPathResource;
6+
import org.w3c.dom.Document;
7+
import org.w3c.dom.Node;
8+
import org.w3c.dom.NodeList;
9+
10+
import javax.xml.parsers.DocumentBuilder;
11+
import javax.xml.parsers.DocumentBuilderFactory;
12+
import java.io.File;
13+
import java.util.ArrayList;
14+
15+
public class SafeDomainParser {
16+
17+
private static Logger logger= LoggerFactory.getLogger(SafeDomainParser.class);
18+
19+
public SafeDomainParser(){
20+
21+
String safeTag = "safedomain";
22+
String domainSafeTag = "domain";
23+
String safeDomainClassPath = "url" + File.separator + "safe_domain.xml";
24+
ArrayList<String> safeDomains = new ArrayList<>();
25+
26+
try {
27+
// 读取resources目录下的文件
28+
ClassPathResource resource = new ClassPathResource(safeDomainClassPath);
29+
File file = resource.getFile();
30+
31+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
32+
DocumentBuilder db = dbf.newDocumentBuilder();
33+
Document doc = db.parse(file); // parse xml
34+
35+
NodeList rootNode = doc.getElementsByTagName(safeTag);
36+
Node domainsNode = rootNode.item(0);
37+
NodeList child = domainsNode.getChildNodes();
38+
39+
for (int i = 0; i < child.getLength(); i++){
40+
Node node = child.item(i);
41+
if (node.getNodeName().equals(domainSafeTag)) {
42+
safeDomains.add(node.getTextContent());
43+
}
44+
}
45+
46+
}catch (Exception e){
47+
logger.error(e.toString());
48+
}
49+
50+
WebConfig wc = new WebConfig();
51+
wc.setSafeDomains(safeDomains);
52+
}
53+
}
54+
55+
56+
57+

src/main/java/org/joychou/config/WebConfig.java

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.springframework.beans.factory.annotation.Value;
44
import org.springframework.stereotype.Component;
55

6+
import java.util.ArrayList;
7+
68

79
/**
810
* Solve can't get value in filter by @Value when not using embed tomcat.
@@ -19,6 +21,7 @@ public class WebConfig {
1921
private static String[] referUris;
2022
private static Boolean referSecEnabled = false;
2123
private static String businessCallback;
24+
private static ArrayList<String> safeDomains= new ArrayList<>();
2225

2326
/**
2427
* application.properties里object自动转jsonp的referer校验开关
@@ -91,4 +94,11 @@ public static String getBusinessCallback(){
9194
return businessCallback;
9295
}
9396

97+
98+
public void setSafeDomains(ArrayList<String> safeDomains){
99+
WebConfig.safeDomains = safeDomains;
100+
}
101+
public static ArrayList<String> getSafeDomains(){
102+
return safeDomains;
103+
}
94104
}

src/main/java/org/joychou/controller/Cors.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
public class Cors {
2121

2222
private static String info = "{\"name\": \"JoyChou\", \"phone\": \"18200001111\"}";
23-
private static String[] urlwhitelist = {"joychou.org", "joychou.me"};
24-
2523

2624
@RequestMapping("/vuln/origin")
2725
public static String vuls1(HttpServletRequest request, HttpServletResponse response) {
@@ -108,7 +106,7 @@ public String seccode(HttpServletRequest request, HttpServletResponse response)
108106

109107
// 如果origin不为空并且origin不在白名单内,认定为不安全。
110108
// 如果origin为空,表示是同域过来的请求或者浏览器直接发起的请求。
111-
if ( origin != null && SecurityUtil.checkURLbyEndsWith(origin, urlwhitelist) == null ) {
109+
if ( origin != null && SecurityUtil.checkURL(origin) == null ) {
112110
return "Origin is not safe.";
113111
}
114112
response.setHeader("Access-Control-Allow-Origin", origin);

src/main/java/org/joychou/controller/URLRedirect.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ public static void forward(HttpServletRequest request, HttpServletResponse respo
7575

7676
/**
7777
* Safe code of sendRedirect.
78-
* http://localhost:8080/urlRedirect/sendRedirect_seccode?url=http://www.baidu.com
78+
* http://localhost:8080/urlRedirect/sendRedirect/sec?url=http://www.baidu.com
7979
*/
80-
@RequestMapping("/sendRedirect_seccode")
80+
@RequestMapping("/sendRedirect/sec")
8181
@ResponseBody
82-
public static void sendRedirect_seccode(HttpServletRequest request, HttpServletResponse response) throws IOException{
82+
public void sendRedirect_seccode(HttpServletRequest request, HttpServletResponse response)
83+
throws IOException{
8384
String url = request.getParameter("url");
84-
String urlwhitelist[] = {"joychou.org", "joychou.com"};
85-
if (SecurityUtil.checkURLbyEndsWith(url, urlwhitelist) == null) {
85+
if (SecurityUtil.checkURL(url) == null) {
8686
// Redirect to error page.
8787
response.sendRedirect("https://test.joychou.org/error3.html");
8888
return;

src/main/java/org/joychou/controller/jsonp/JSONP.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@
2424
* https://github.com/JoyChou93/java-sec-code/wiki/JSONP
2525
*/
2626

27-
2827
@RestController
2928
@RequestMapping("/jsonp")
3029
public class JSONP {
3130

32-
private static String[] urlwhitelist = {"joychou.com", "joychou.org"};
33-
private static String callback = WebConfig.getBusinessCallback();
31+
private String callback = WebConfig.getBusinessCallback();
3432

3533
// get current login username
3634
public static String getUserInfo2JsonStr(HttpServletRequest request) {
@@ -65,7 +63,7 @@ public String referer(HttpServletRequest request) {
6563
public String emptyReferer(HttpServletRequest request) {
6664
String referer = request.getHeader("referer");
6765

68-
if (null != referer && SecurityUtil.checkURLbyEndsWith(referer, urlwhitelist) == null) {
66+
if (null != referer && SecurityUtil.checkURL(referer) == null) {
6967
return "error";
7068
}
7169
String callback = request.getParameter(this.callback);
@@ -110,7 +108,7 @@ public ModelAndView mappingJackson2JsonView(HttpServletRequest req) {
110108
public String safecode(HttpServletRequest request) {
111109
String referer = request.getHeader("referer");
112110

113-
if (SecurityUtil.checkURLbyEndsWith(referer, urlwhitelist) == null) {
111+
if (SecurityUtil.checkURL(referer) == null) {
114112
return "error";
115113
}
116114
String callback = request.getParameter(this.callback);

src/main/java/org/joychou/filter/JsonpFilter.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain filter
3939
HttpServletResponse response = (HttpServletResponse) res;
4040

4141
String refer = request.getHeader("referer");
42-
String[] jsonpReferWhitelist = WebConfig.getJsonpReferWhitelist();
4342
StringBuffer url = request.getRequestURL();
4443
String query = request.getQueryString();
4544

@@ -50,7 +49,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain filter
5049
}
5150

5251
// 校验jsonp逻辑,如果不安全,返回forbidden
53-
if (SecurityUtil.checkUrlByGuava(refer, jsonpReferWhitelist) == null ){
52+
if (SecurityUtil.checkURL(refer) == null ){
5453
logger.error("[-] URL: " + url + "?" + query + "\t" + "Referer: " + refer);
5554
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
5655
response.getWriter().write("forbidden");
@@ -87,7 +86,7 @@ private boolean check(HttpServletRequest req) {
8786
break;
8887
}
8988
}
90-
if (StringUtils.isBlank(reqCallback)){
89+
if(StringUtils.isBlank(reqCallback)){
9190
return false;
9291
}
9392

src/main/java/org/joychou/filter/OriginFilter.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
@WebFilter(filterName = "OriginFilter", urlPatterns = "/cors/sec/originFilter")
2121
public class OriginFilter implements Filter {
2222

23-
private static String[] urlwhitelist = {"joychou.org", "joychou.me"};
24-
2523
@Override
2624
public void init(FilterConfig filterConfig) throws ServletException {
2725

@@ -40,7 +38,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain filter
4038
logger.info("[+] Origin: " + origin + "\tCurrent url:" + request.getRequestURL());
4139

4240
// 以file协议访问html,origin为字符串的null,所以依然会走安全check逻辑
43-
if ( origin != null && SecurityUtil.checkURLbyEndsWith(origin, urlwhitelist) == null) {
41+
if ( origin != null && SecurityUtil.checkURL(origin) == null) {
4442
logger.error("[-] Origin check error. " + "Origin: " + origin +
4543
"\tCurrent url:" + request.getRequestURL());
4644
response.setStatus(response.SC_FORBIDDEN);

src/main/java/org/joychou/filter/ReferFilter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain filter
6464
String reqCallback = request.getParameter(WebConfig.getBusinessCallback());
6565
if ("GET".equals(request.getMethod()) && StringUtils.isNotBlank(reqCallback) ){
6666
// If the check of referer fails, a 403 forbidden error page will be returned.
67-
if (SecurityUtil.checkURLbyEndsWith(refer, WebConfig.getReferWhitelist()) == null ){
67+
if (SecurityUtil.checkURL(refer) == null ){
6868
logger.info("[-] URL: " + request.getRequestURL() + "?" + request.getQueryString() + "\t"
6969
+ "Referer: " + refer);
7070
response.setStatus(HttpServletResponse.SC_FORBIDDEN);

src/main/java/org/joychou/security/CustomCorsProcessor.java

+6-11
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,21 @@ protected String checkOrigin(CorsConfiguration config, String requestOrigin) {
2929
if (result != null) {
3030
return result;
3131
}
32-
33-
List<String> allowedOrigins = config.getAllowedOrigins();
34-
if (StringUtils.isBlank(requestOrigin)
35-
|| CollectionUtils.isEmpty(allowedOrigins)) {
32+
// List<String> allowedOrigins = config.getAllowedOrigins();
33+
if (StringUtils.isBlank(requestOrigin)) {
3634
return null;
3735
}
3836

39-
return customCheckOrigin(allowedOrigins, requestOrigin);
37+
return customCheckOrigin(requestOrigin);
4038
}
4139

4240

4341
/**
44-
* 用host的endsWith来校验requestOrigin
42+
* 校验requestOrigin
4543
*/
46-
private String customCheckOrigin(List<String> allowedOrigins, String requestOrigin) {
47-
48-
// list转String[]
49-
String[] arrayAllowOrigins = allowedOrigins.toArray(new String[allowedOrigins.size()]);
44+
private String customCheckOrigin(String requestOrigin) {
5045

51-
if ( SecurityUtil.checkURLbyEndsWith(requestOrigin, arrayAllowOrigins) != null) {
46+
if ( SecurityUtil.checkURL(requestOrigin) != null) {
5247
logger.info("[+] Origin: " + requestOrigin );
5348
return requestOrigin;
5449
}

0 commit comments

Comments
 (0)