跨越问题浅析及Java后端解决方案

域既是 Windows 网络操作系统的逻辑组织单元,也是Internet的逻辑组织单元,它是安全边界
只有域的所有者才能访问管理域内部的资源,若其他的域要访问或者管理,则需要该域赋予其他域相关权限。

发生跨域请求的情况

当请求的资源与当前所在页面的资源的服务器不同的域、协议或端口不同的时候,如http://192.168.3.122:8080 这样一个地址。

  1. 域不同,地址换成了 192.168.3.123
  2. 协议不同,http变成了https
  3. 端口不同,原来是8080,换成了8081
  4. 在以上这些情况就会引起跨域问题。跨域一般产生在js的代码中,src等路径一般可以直接访问跨域资源

浏览器的同源策略

主要有两种

  1. DOM 同源策略 : 禁止对不同源页面的 Dom 元素进行操作,主要是在 iframe 标签加载跨域页面出现。

  2. XMLHttpRequest 同源策略 : 禁止使用 XHR 对象对不同源地址发起请求。

存储在浏览器中的数据,如localStroage、Cookie和IndexedDB不能通过脚本跨域访问

CSRF跨站请求伪造

如果没有 XHR 同源策略,以及不允许跨域获取cookies等的限制

那么攻击者将可以发起 **CSRF (跨站请求伪造) **攻击场景可以如下:

  1. 你登录了某个银行网站,银行网站返回你的登录状态并且保存在cookies中。
  2. 你没有安全退出清空cookies,又刚好不小心浏览到了恶意网站
  3. 一进入恶意网站,它将会向 银行网站 发起XHR请求。(发送请求将会带上目标网站设置的cookies)
  4. 银行拿到cookies,验证通过,返回数据。

CORS 跨域资源共享

CORS 是一个 W3C标准,该标准定义了在访问跨域资源时,服务端和客户端需要如何沟通,如何授权信任

原理:使用 http自定义头部 ,请求头附带客户端信息,服务端验证,并且返回响应头告诉客户端是否允许访问。

该标准需要客户端和服务端同时配合支持,当前所有的浏览器都支持该标准。 对于用户是无感知的,由浏览器自动完成只需要由服务端改动,前端不需要改动。

CORS将http请求分为简单请求非简单请求

非简单请求

  • 跨域预检请求
  1. 在发送真正请求之前,会先发送一次预检请求,来判断服务端是否支持非简单请求的类方法。预检请求包含跟简单请求一样的,还有指定

    允许访问该资源的外域 URIAccess-Control-Allow-Origin

    真实请求的方法Access-Control-Request-MethodPUTDELETE

    是否需要附带cookie信息Access-Control-Allow-Credentials: true

    自定义复杂头部Access-Control-Request-Headers(可选)

  2. 预检通过之后,浏览器会再次使用真实请求方法发起请求

第一次发送options方法进行预检请求,第二次才是真发送put,delect等方法。

注:在一个页面中,预检操作只需要进行一次。

OPTIONS
查询支持的方法
查询指定的 URL 能够支持的方法。
会返回 Allow: GET, POST, HEAD, OPTIONS 这样的内容

Java后端解决跨域方案拦截器WebMvcConfigurer

存笔记,方便以后Copy

前后端都需要解决跨域问题的方式有很多,Java解决的方式主要是添加注解的方式和采用添加拦截器的方法。

WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,提供很多自定义的拦截器,例如跨域设置、类型转化器等等

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 解决跨域问题
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

如果整合到Shiro+Jwt组合的安全拦截验证框架中,还需要再JwtFilter中加入,重写preHandle方法

@Component
public class JwtFilter extends AuthenticatingFilter {

    @Autowired
    JwtUtils jwtUtils;
	...... 
	.....
	....其他方法,例如AuthenticationToken,onAccessDenied....
	...
	..
	.
   
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        //跨域处理
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
        httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        // 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpServletResponse.setStatus(org.springframework.http.HttpStatus.OK.value());
            return false;
        }

        return super.preHandle(request, response);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值