业务需求
http请求的配置,决定了该网站的安全性,跨域等问题,让我们一起来看看Javashop电商系统中是如何解决的
先一起了解一下Http请求的常见配置:
一、http请求常见配置及其说明
General :
Request URL:资源的请求url
Request Method:HTTP方法
Status Code:响应状态码
1 200(状态码) OK(原因短语) 2 301 - 资源(网页等)被永久转移到其它URL 3 404 - 请求的资源(网页等)不存在 4 500 - 内部服务器错误
Remote Address:远程地址/来源
Referrer-Policy:
1 空字符串 若设为空串则默认按照浏览器的机制设置referrer的内容,默认情况下是和no-referrer-when-downgrade设置得一样。 no-referrer 不显示referrer的任何信息在请求头中。 2 no-referrer-when-downgrade 这是默认值。当从https网站跳转到http网站或者请求其资源时(安全降级HTTPS→HTTP),不显示referrer的信息,其他情况(安全同级HTTPS→HTTPS,或者HTTP→HTTP)则在referrer中显示完整的源网站的URL信息。 3 same-origin 表示浏览器只会显示referrer信息给同源网站,并且是完整的URL信息。所谓同源网站,是协议、域名、端口都相同的网站。 4 origin 表示浏览器在referrer字段中只显示源网站的源地址(即协议、域名、端口),而不包括完整的路径。 5 strict-origin 该策略更为安全些,和origin策略相似,只是不允许referrer信息显示在从https网站到http网站的请求中(安全降级)。 6 origin-when-cross-origin 当发请求给同源网站时,浏览器会在referrer中显示完整的URL信息,发个非同源网站时,则只显示源地址(协议、域名、端口) 7 strict-origin-when-cross-origin 和origin-when-cross-origin相似,只是不允许referrer信息显示在从https网站到http网站的请求中(安全降级)。 8 unsaft-url 浏览器总是会将完整的URL信息显示在referrer字段中,无论请求发给任何网站
Request Headers:
//指定允许其他域名访问Access-Control-Allow-Origin:http:/'//一般用法(*,指定域,动态设置),3是因为*不允许携带认证头和cookies//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回'Access-Control-Allow-Credentials:true'
请求头origin字段为当前域
Cache-Control 来控制页面的缓存与否,这里介绍几个常用的参数:
no-cache,浏览器和缓存服务器都不应该缓存页面信息;public,浏览器和缓存服务器都可以缓存页面信息;no-store,请求和响应的信息都不应该被存储在对方的磁盘系统中;must-revalidate,对于客户机的每次请求,代理服务器必须想服务器验证缓存是否过时max-age 在此值内的时间里就不会重新访问服务器
Connection——决定当前的事务完成后,是否会关闭网络连接;
Content-Security-Policy: 内容安全策略
1 script-src 定义js文件的过滤策略 2 'self' 同源策略,即允许同域名同端口下,同协议下的请求 3 'unsafe-inline' 允许行内代码执行frame-ancestors 政策设置一个或多个来源
Content-Type:text/html ——服务端发送的类型及采用的编码方式
Expires——包含日期/时间, 即在此时候之后,响应过期
Pragma:no-cache ——服务端禁止客户端缓存页面数据
Server:nginx/1.14.0 ——服务端的Web服务端名
Strict-Transport-Security——用来告诉浏览器在指定时间内,这个网站必须通过HTTPS协议来访问。也就是对于这个网站的HTTP地址,浏览器需要先在本地替换为HTTPS之后再发送请求。
Transfer-Encoding——指定报文主体的传输编码方式
Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头, 应该用一个缓存的回复(response)还是向源服务器请求一个新的回复
X-Content-Type-Options HTTP 消息头相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定
X-Frame-Options: 用来给浏览器 指示允许一个页面 可否在 <frame>, <iframe>, <embed> 或者 <object> 中展现的标记
1 deny 表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。 2 sameorigin 表示该页面可以在相同域名页面的 frame 中展示。 3 allow-from uri 表示该页面可以在指定来源的 frame 中展示。
X-XSS-Protection 启用XSS过滤。 如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载。
Response Headers
Accept 请求头用来告知(服务器)客户端可以处理的内容类型,这种内容类型用MIME类型来表示
Accept-Encoding:gzip, deflate ——客户端能接收的压缩数据的类型
Accept-Language:en-US,en;q=0.8 ——客户端接收的语言类型
Authorization: 令牌
Host: api.javamall.com.cn 连接的目标主机和端口号
Referer——对请求中 URI 的原始获取方
Sec-Fetch-Dest: empty 取元数据报头指示该请求的目的地,即所获取的数据将如何使用。空的???
Sec-Fetch-Mode: cors 获取元数据标头表明了一个请求的模式。允许跨域
Sec-Fetch-Site 获取元数据标头表明了一个请求发起者的来源与目标资源来源之间的关系
1 cross-site 请求的发起源与资源源完全不相同 2 same-origin 请求的发起源与资源源完全相同 3 same-site 请求的发起源与资源源部分相同:同一顶级域名下的二级域名none
User-Agent: ——客户端版本号的名字
UUID 是 通用唯一识别码
二、源码
在javshop电商系统中,我们如何解决跨域访问的问题呢?
以下就是解决方案:在SellerSecurityConfig 类中
1 /** 2 * 定义跨域配置 3 * @return 4 */ 5 @Bean 6 CorsConfigurationSource corsConfigurationSource() { 7 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 8 CorsConfiguration config = new CorsConfiguration(); 9 config.setAllowCredentials(true); 10 config.addAllowedOrigin(CorsConfiguration.ALL); 11 config.addAllowedHeader(CorsConfiguration.ALL); 12 config.addAllowedMethod(CorsConfiguration.ALL); 13 source.registerCorsConfiguration("/**", config); 14 return source; 15 }
并且 在JavashopRequestInterceptor 类中 加入 javashop 跨域的支持
1 /** 2 * 验证referer 3 * 4 * @param request 5 * @param response 6 * @return 7 */ 8 private boolean checkReferer(HttpServletRequest request, 9 HttpServletResponse response) { 10 if (!checked) { 11 return true; 12 } 13 String referer = request.getHeader("referer"); 14 String host = request.getServerName(); 15 String uri = request.getRequestURI(); 16 17 logger.debug("referer=" + referer); 18 logger.debug("uri=" + request.getRequestURI()); 19 20 boolean flag = uri.startsWith("/client") 21 || "/load-customwords".equals(uri) 22 || "/swagger-ui.html".equals(uri) 23 || uri.startsWith("/order/pay/weixin") 24 || uri.startsWith("/payment/callback") 25 || uri.startsWith("/payment/return") 26 || uri.contains("/callback") 27 || uri.startsWith("/passport/connect"); 28 if (referer == null && flag) { 29 // 状态置为404 30 return true; 31 } else if (referer == null) { 32 response.setStatus(HttpServletResponse.SC_NOT_FOUND); 33 logger.debug("本次请求的referer为空"); 34 return false; 35 } 36 37 java.net.URL url = null; 38 try { 39 url = new java.net.URL(referer); 40 } catch (MalformedURLException e) { 41 // URL解析异常,也置为404 42 response.setStatus(HttpServletResponse.SC_NOT_FOUND); 43 return false; 44 } 45 // 首先判断请求域名和referer域名是否相同 46 if (!host.equals(url.getHost())) { 47 // 如果不等,判断是否在白名单中 48 if (javashopConfig.getReferer() != null) { 49 for (String s : javashopConfig.getReferer()) { 50 if (matcher.match(s, url.getHost())) { 51 return true; 52 } 53 } 54 } 55 logger.debug("当前referer没有加入到配置中:" + url.getHost()); 56 return false; 57 } 58 return true; 59 }
在javshop电商系统中,我们如何防止夸站点脚本攻击的问题呢?
1 /** 2 * 3 * 加载自定义的 拦截器 4 * @author Chopper 5 * @version v1.0 6 */ 7 @Configuration 8 public class WebInterceptorConfigurer implements WebMvcConfigurer { 9 /** 10 * 自定义 ObjectMapper ,用于xss攻击过滤 11 * @param builder 12 * @return 13 */ 14 @Bean 15 @Primary 16 public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) { 17 //解析器 18 ObjectMapper objectMapper = builder.createXmlMapper(false).build(); 19 //注册xss解析器 20 SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer"); 21 xssModule.addSerializer(new XssStringJsonSerializer()); 22 objectMapper.registerModule(xssModule); 23 //返回 24 return objectMapper; 25 } 26 }
方法类
1 public String clean(String value) { 2 //此处定义的标签是Whitelist.basicWithImages()中可以放过的标签 3 List<String> tags = Arrays.asList("a", "b", "blockquote", "br", ... "source"); 4 Whitelist whiteList = Whitelist.basicWithImages(); 5 6 for(String tag : tags){ 7 whiteList.addAttributes(tag,"style","class","width","align","src", "controls", "preload", "height", "data-setup", "type"); 8 } 9 10 value = Jsoup.clean(value, whiteList); 11 12 return value.replace("&","&"); 13 }
在javshop电商中,我们如何防止非同源frame的问题呢?
在nginx 中的server如下配置
1 add_header X-Frame-Options SAMEORIGIN;
在javshop电商中,我们如何设置 脚本执行策略的呢?
nginx 添加
1 add_header Content-Security-Policy "script-src 'self' api.javamall.com.cn 'unsafe-eval' 'unsafe-inline' ... *.aliyun.com *.alibaba.com *.aliapp.org";