记一次实践经历——在Java环境下解决跨源问题的常用手段:过滤器(Filter)

尝试真正的前后端分离

笔者在此前有做过一些小项目,不过大抵都侧重后端这方面,还未真正做过要把前端同时考虑在内的实践。即便是有,但所用技术也是比较落后的JSP(JSP本身也不是前端领域,来进行前后端数据传输尚且有点作用),并不能和后端解耦,做到真正的分离。

真正要想做到解耦、做到一般业务场景的前后端分离,就需要强调接口思想,前后端之间的交互都交由接口来解决,过程只需要传递相关的请求参数就可以了。这样才算做到分离,前后端的任务也能更为明晰,也不会出现笔者完成当初JSP项目时的一大堆代码冲突了()。

所需要的技术自然就必须淘汰JSP,而需要利用到Vue做数据绑定,axios进行异步请求------当然,在前端领域,所用技术还远不止这些,这里只是结合笔者最近的一次的实践。

同源策略

然而,前后端做完分离后,又该考虑一个问题了------前后端设置的URL默认往往是不一样的,这也就是为什么在使用Axios发送请求时,url都写成绝对路径的原因。

vue 复制代码
axios({
    method:"post",
    url:"http://localhost:8080/brand_case_war/brand/update",//绝对路径
    data:_this.brand
}).then(function (resp){
    if(resp.data==="success"){
        //更新成功
        //关闭窗口
        _this.dialogVisible=false;
        _this.select();
        _this.$message({
            message:'更新成功',
            type:'success'
        })
    }
})

这样做也符合解耦、分离的原则嘛。但是如果不做任何其他处理就直接运行整个项目的话,我们很快就能发现前端传递的参数,后端程序总是接收不到,页面打开F12,我们能发现这样的报错:

报错信息表明了一个跨源资源共享(CORS) 问题,当我们尝试从浏览器的某个源(这里是 http://localhost:8080)发起请求到另一个源时就会出现这样的问题。

那么想了解跨源资源共享,首先就必须先知道同源策略(SOP)是怎么一回事:

同源策略(Same-Origin Policy) 是 Web 浏览器中的一项安全机制,旨在防止不同源(协议、域名或端口不同的网站)之间的恶意交互。这个策略的核心思想是,如果两个资源(如网页、图片、脚本等)来自同一个源,那么它们可以自由地相互通信和操作;如果来自不同的源,浏览器会限制它们之间的交互,以防止潜在的安全风险,如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)。

同源策略的主要目的是保护用户数据和隐私,防止恶意网站通过脚本窃取或篡改其他网站的数据。例如,如果一个用户在一个银行网站上操作,而另一个恶意网站试图通过 JavaScript 来获取这个银行网站的数据,由于同源策略的存在,这种尝试通常会被浏览器阻止。

SOP为我们带来了安全,但同时也为Web开发多了一项新增的环节:在安全的前提下,允许跨源资源共享,就是和SOP相对的CORS。

利用过滤器解决跨源问题

笔者对于SOP和CORS都只处于认识层次,且本文侧重也不在这两者上,因此对于这两者的介绍就只能停留到这儿。

回到笔者最近的实践上,在了解了CORS后,再来看这一处报错,这其中还提到了在即将发送的response当中,有名为Access-Control-Allow-Headers的一个字段。

再去查阅资料,发现这一字段是CORS的核心,跨源资源共享失败的很大原因可以在这个字段中找到。

  1. 服务器未正确设置 CORS 头部 :如果服务器没有在响应中包含正确的 Access-Control-Allow-Origin 头部,或者该头部的值不正确,浏览器会阻止跨域请求。
  2. 请求方法或头部不被允许 :如果请求使用了非简单 HTTP 方法(如 PUT、DELETE 等)或者自定义头部,服务器需要在 Access-Control-Allow-MethodsAccess-Control-Allow-Headers 头部中明确允许这些方法和头部,否则浏览器也会阻止跨域请求。

因此,我们有必要对这个字段进行设置,最常见的操作是这样的:

java 复制代码
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
//这里的IP和端口可以改成你自己的
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Max-Age", "3600");

由于这样的跨源问题几乎都发生在Web上,因此我们使用主要作用在Java Web上的过滤器(Filter),注解写上拦截路径。

java 复制代码
@WebFilter("/*")//处理所有资源请求
public class CorsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init CorsFilter......");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "3600");
        chain.doFilter(req, res);
    }

    @Override
    public void destroy() {
        System.out.println("destroy CorsFilter......");
    }
}

解决跨域问题,这种方法很常用。

过滤器(Filter)和中间件(Middleware)

之前做用户鉴权的时候也用过中间件,此次实践不由得将它和过滤器对比了下,发现两者作用有些相似------都是到达目标资源之前先进行一趟数据处理,再放行。

但细想,过滤器更多的用在Java Web中,处理HTTP请求尤其是;而中间件范围更加宽泛,不只在Web当中扮演角色,更可以用于路由、数据校验、会话管理、错误处理等多种任务当中。

查询资料,两者的对比比较详细一点是这样的:

相关推荐
救救孩子把15 分钟前
深入理解 Java 对象的内存布局
java
落落落sss17 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
万物皆字节23 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
程序员-珍27 分钟前
虚拟机ip突然看不了了
linux·网络·网络协议·tcp/ip·centos
夜雨翦春韭30 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
我行我素,向往自由36 分钟前
速成java记录(上)
java·速成
一直学习永不止步42 分钟前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
邵泽明43 分钟前
面试知识储备-多线程
java·面试·职场和发展
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
煸橙干儿~~1 小时前
分析JS Crash(进程崩溃)
java·前端·javascript