Flutter WebView 如何与 h5 同步登录状态

news2024/9/21 8:00:17

在这里插入图片描述
大家好,我是 17。

Flutter WebView 一共三篇文章

  1. 在 Flutter 中使用 webview_flutter 4.0 | js 交互
  2. Flutter WebView 性能优化,让 h5 像原生页面一样优秀
  3. Flutter WebView 如何与 h5 同步登录状态

本篇是第 3 篇,讲下 Flutter WebView 与 h5 如何同步状态。

缘起

本来是没有这一篇的,完成前两篇后,关于 WebView 的文章就结束了。

第 2 篇 发出来后,小伙伴 枉费 发评论说:敢问下篇是不是该轮到cookie了!

image.png

我看到的第一反应是 cookie 内容有点少,怎么也不足以写成一篇文章吧。但转念一想,最近写文太辛苦了,每个周末都大门不出,二门不入,都不知有汉了。现在有 枉费 的提议在先,就算写篇水文,也是顺理成章的事情了。于是心中大喜,回复说:“你说的是在 Flutter WebView 中使用 cookie 吧,那太好了,正好可以写篇水文轻松一下。谢谢你的点赞!”,嘿嘿,前端可是咱的老本行, wpw!。写的时候才发现,写好了也是不容易的。cookie 的内容也不少,可能是前端做的久了,感觉 cookie 是理所当然的事情,所以才有不知道写什么的感觉。 虽然比上周轻松多了,但也又花了一个周末!我还是想尽力写好,尽量点到每个重要的知识点。简单的内容,17 也想写的有色彩,不能仅满足于会同步设置 token,还需要了解如何保障 token 的安全,这样会显示比较专业。

cookie 简介

为什么要介绍 cookie

cookie 对于前端小伙伴来说 cookie 再熟悉不过了,但其它端如果没有用过类似的东西不知道也很正常。虽然网上的资料很多,但是对于新手来说,还是无从分辨的,不知道应该看哪些内容,我就一起都说了吧。

cookie 定义

HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器会存储 cookie 并在下次向同一服务器再发起请求时携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器——如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。

HTTP 是无状态的:在同一个连接中,两个执行成功的请求之间是没有关系的。这就带来了一个问题,用户没有办法在同一个网站中进行连续的交互,比如在一个电商网站里,用户把某个商品加入到购物车,切换一个页面后再次添加了商品,这两次添加商品的请求之间没有关联,浏览器无法知道用户最终选择了哪些商品。而使用 HTTP 的标头扩展,HTTP Cookie 就可以解决这个问题。把 Cookie 添加到标头中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。

注意,HTTP 本质是无状态的,使用 Cookie 可以创建有状态的会话。

以上内容节选自 MDN

保存在本地的意思是保存在本地的磁盘上,当你关闭浏览器甚至关机都没关系,下次打开浏览器的时候它还在。因为每次都会随域名自动发送,cookie 不宜太大,一般不超过 4KB。

token 的作用

token 的作用我举个例子,就是我去你家串门,第一次到你家,你不认识我,问:你是谁?我回答:我是 17。然后你让我进门了。第二次去你家,你还是不认识我,因为每次串门都是完全独立的,可以当作从没来过你家。你依旧问:你是谁?我回答:我是 17,你又让我进门了。如果我经常去你家串门每次都问还是很麻烦的。所以你就给我了一个能证明我身份的令牌(token),我再次到你家串门的时候,直接拿出令牌,令牌上可能是这样写的:我是 17,我们见过的。你一看,啊,原来是 17 啊,快请进。

token 就相当于是这样的令牌。一个用户在网站的一个页面中登录了,他的登录信息会保存在 cookie 里,在访问下一个页面的时候,浏览器会带上 cookie 的信息向服务器请求页面,服务器根据 cookie 的信息就知道你是否登录了。
token 相当于一把钥匙,能开锁。通过 token 无法反解出用户名和密码。密码不要直接放在 cookie 中。

cookie 可以有很多 key value,token 只是这众多的 key value 中的一个

Flutter WebView 中 cookie 的基本操作。

在 webview_flutter 4 中有 cookieManager 专门用来管理 WebView 中的 cookie,我们先来学习下用法。

用 WebViewCookie 设置 cookie

 cookieManager.setCookie(
      const WebViewCookie(
        name: 'IAM17',
        value: 'FE',
        domain: 'juejin.cn',
      ),
  );

这样就行了,很简单吧。还有一个参数 path,默认是 ‘/’。 setCookie 返回的是 Future<void>

用 cookieManager 清除 cookie

cookieManager.clear() 这个就太简单了。直接清除就好了。需要注意的是,这个方法杀伤力有点大,是无差别攻击,所有 WebView 实例中的 cookie 都会被清除,慎用!。

cookieManager 的能力也就到此为止了,即不能读 cookie,也不能删除单条 cookie,剩下的还指望万能的 javascript。

用 js 设置 cookie

虽然 cookieManager.setCookie 的方法很好用,但有的时候,你可能需要用 js 来设置 cookie。

最简单的只要一个key,一个value,这样设置的 cookie 是一个会话 cookie,浏览器关闭后 cookie 失效。

var key='name',value='IAM17';
document.cookie = `${key}=${encodeURIComponent(value)}`;

要想在一段时间内有效,加上 expires 参数。

var key='name',value='IAM17';
var now = new Date();
// 设置一天有效期
now.setTime(now.getTime() + 1000*60*60*24);
var expires=now.toGMTString();
document.cookie = `${key}=${encodeURIComponent(value)};expires=${expires}`;

设置 cookie 在整个网站有效

var key='name',value='IAM17';
document.cookie = `${key}=${encodeURIComponent(value)};path=/`;

还有三个与安全相关的参数,了解下含义,后面会详细讲。

  • httponly 禁止 js 读取
  • secure 只能通过 https 传输
  • SameSite 现代浏览器支持的安全相关的属性

准备好 js 后,这样执行

 final controller = WebViewController();
 controller.runJavaScript('你的 js ');

用 js 读取 cookie

   final cookies = await controller
           .runJavaScriptReturningResult('document.cookie') as String;

这样读出来的是一个字符串,用起来并不方便, 17 准备了一方法,把字符串解析成 map,贴心吧!

  getCookie(WebViewController controller) async {
    final controller = WebViewController();
    var cookies = await controller
        .runJavaScriptReturningResult('document.cookie') as String;
  
    var list = cookies.split('; ');
    var map = <String, String>{};
    for (var item in list) {
      var cookieItem = item.split('=');
      map[cookieItem[0]] = cookieItem[1];
    }
    return map;
  }

;(分号)后面是一个英文空格

用 js 删除单条 cookie

比如你想删除一个 key 为 token 的 cookie

controller.runJavaScript(
          'document.cookie = "token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"');

可以不指定 value,指定了也没关系。

js 清除本域名下所有 cookie

js 可以删除本域名下的 cookie。

function clearAllCookie() {
    var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
    if(keys) {
	for(var i = keys.length; i--;)
	   document.cookie = keys[i] + '=;expires=' + new Date(0).toUTCString()
        }
    }
}

^ 后面是一个英文空格

可能有的同学对正则不是很熟悉,我把正则表达式解释一下。已经掌握的同学自行跳过。

[^\s=;]+ 含义为匹配 除空格等号分号外的至少一个连续字符。比如 a11a,都可以,但是空字符串不行,因为至少要一个字符;a b 不行,因为有空格;a=b 不行;因为有等号,;c 不行,因为有分号。

(?=\=) 这是一个零宽肯定先行断言,听术语有点迷糊,还是举例说明。name=17 用这个零宽肯定先行断言匹配的结果就是 e = 之前的那个位置。零宽的意思是不匹配任何字符,只匹配位置。

零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已。给指定位置添加一个限定条件,用来规定此位置之前或者之后的字符必须满足限定条件才能使正则中的字表达式匹配成功。

现在把它们合在一起 [^\s=;]+(?=\=),可以匹配 除空格等号分号外的至少一个连续字符并且后面紧跟着等号。

\ 是转义符,这里不加转义其实也可以,因为前面有 ?=,加一个 \ 会显得清晰一些。

g 表示全局匹配,否则只匹配第一个。

最后把这个函数用 runJavaScript 执行一下就好了。

基础用法已经讲完了,下面我们实战一下。

登录状态同步

用到 cookie 的最经典的应用当属登录状态保持了。 h5 可以单独登录,app 也可以单独登录,理想状态下,两端的登录状态应该保持一致,就需要登录状态的同步了。

app 同步登录状态到 h5

WebView 刚打开的时候,需要把 app 的登录状态同步到 h5。

先写入准备好的 token,再打开对应的 h5 就行了。

setCookie() async {
    final manager = WebViewCookieManager();
    await cookieManager.setCookie(
      const WebViewCookie(
        name: 'token',
        value: 'IAM17',
        domain: 'csdn.net',
      ),
    );
    await controller.loadRequest(Uri.parse(
        'https://csdn.net'));
  }

如果没有域名,用 IP 也是可以的,内网外网的 IP 都行。

当然了,调用 js 写入 cookie 也是可以的,但既然有 cookieManager.setCookie,用这个方法更方便,还不用等页面加载完成。

h5 同步登录状态到 app

app 的状态是未登录,打开 h5 后, h5 自己在网页中登录了。如何同步到 app 呢?

二个办法

  1. 如果是单独的登录页面,app 拦截登录页面的请求后,在 app 中登录,再把状态同步到 h5。
  2. js 调用 JavaScriptChannel 设置的对象方法。

第 1 种方法可以拦截真正的页面地址,也可以拦截和 app 约定好的地址。

第 2 种方法 js 调用登录接口,登录后,再调用 JavaScriptChannel 方法把 token 同步给 app。
当然了,js 调用 JavaScriptChannel 方法通知 app 登录,app 再同步回 h5 也是可以的。

如何拦截和交互请参见 在 Flutter 中使用 webview_flutter 4.0 | js 交互

这 2 种方案在前文都已经讲过,不再赘述。

虽然各种方法都可以实现,17 不推荐拦截真正的页面地址,因为这样页面地址就被定死了,不方便修改了。万一哪天域名变更,或路径变更,那就很麻烦了。

登录 token 安全保障

既然 token 是钥匙,那么钥匙被别人拿去了,可就麻烦了,所以要保证 token 的安全。要想知道如何保证安全,就得先知道如何获取 token。

如何获取 token

  1. HTTP 劫持
    一般 HTTP 劫持是劫持 http 请求,篡改HTTP响应体,使用户收到劫持者篡改后的内容。当然 HTTP 劫持也能拿到 cookie 的信息。
  2. 跨站脚本攻击(Cross-site scripting,XSS),CSRF(跨站请求伪造)来盗取 cookie。

XSS 是指攻击者可以利用漏洞在网站上注入恶意的客户端代码。若受害者运行这些恶意代码,攻击者就可以突破网站的访问限制并冒充受害者。

Cookie 往往用来存储用户的身份信息,恶意网站可以设法伪造带有正确 Cookie 的 HTTP 请求,这就是 CSRF 攻击。

预防措施

要防范这两种攻击也很简单。

网站启用 https 就可以预防 HTTP 劫持。如果网页使用 https 传输,cookie 也会使用 https 传输。如果你的网站只支持 Https,cookie 不需要单独设置。如果你的网站还支持 http, 为了安全,可以阻止 cookie 在 http 协议下传输。

Set-Cookie: token=IAM17; Secure

Secure 代表本条 cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,它永远不会使用不安全的 HTTP 发送(本地主机除外),这意味着中间人攻击者无法轻松访问它。无法轻松这样的表述就显示很严谨了。道高一尺,魔高一丈,永远不要把话说满。我曾发过沸点证明自己是程序员:再难的需求也不敢说实现不了。有些小伙伴不理解,直接回实现不了不就得了? 以前我也多次说过“实现不了”,结果每次都被打脸。所以对于有难度的需求,这样回答会比较稳妥:技术方案我还不是很确定,需要调研一下。调研范围不能仅局限于你自己的领域,要全范围调研,首先要搞明白,在全领域范围内,能不能实现。如果不是自己的领域,就可以交差了。凡事都自己亲自调研,既费时还费力,还可能得出错误的结论,所以最好的方案是,每个领域都认识相关的专家,专业的事,专业的人来办。尤其现在人工智能的出现,让很多不可能成为了可能,要自己亲自去补习吗?NO,普通人没有这个精力,你要做的就是成为自己领域的专家。当你可以成为别人的依靠时,别人也会成为你的依靠。

XSS,CSRF 有多种攻击手段,但无论怎样,不管你几路来,我只一路去。预防攻击把 cookie 中的 HttpOnly,Secure,SameSite 一股脑加上就行了。这样就把用 js,传输,请求链接几种可能的获得 token 的路都堵死了。攻击很难再有机会获得 token。

Set-Cookie: token=IAM17; Secure; HttpOnly; SameSite=Strict;

Cookie 的 SameSite 属性用来限制第三方 Cookie,从而减少安全风险。
SameSite 有三个值可以选

  • Strict 最为严格,完全禁止第三方 Cookie。
  • Lax 是默认值,除导航到目标网址的 Get 请求除外,也是禁止第三方Cookie
  • None 陏便发第三方 cookie,但必须同时设置 Secure

第三方Cookie 是指由非当前网站设置的Cookie

比如有两个网站 A,B,A 请求 B 的页面,带上 A 的 cookie 发送给 B ,对于 B 的页面来说,接收到的 cookie 就是 第三方 cookie。SameSite=Strict 禁止 cookie 发送到第三方。也就是说 A 网站的 cookie 这个时候不可能会自动发到 B 网站。

如果 WebView 不支持 SameSite 怎么办。其实不用担心,就算 cookie 没有这些安全设置,h5 也应该有能力保证 token 的安全,防止 XSS,CSRF 的攻击。

js 无法设置 HttpOnly,只能用设置 header 的方式来设置。

如何验证 cookie 有没有设置成功?

用 chrome 打开网页,F12 打开 控制面板。找到应用菜单下的存储下面的 cookie,如果 Secure 处打 ✓ 就说明设置成功了。同样的,如果 httpOnly 设置成功了,HttpOnly处也会打 ✓。Samesite 会显示相应的值。

image.png

知识扩展, LocalStorage

每次都随着请求自动发送,虽然非常便利,但也带来了麻烦,增加了网络传输的负担。有些数据是没有必要每次都传输的。在早期,程序员们想出了分域的办法。比如 js,css,图片用不同的域名。但是 cookie 还有一个问题,容量太小。为了解决这两个问题,LocalStorage 隆重登场了。一起的还有一个 SessionStorage,数据只在一个会话期间内有效。了解下即可,Flutter 这边一般不会用到,如果真的需要存大量数据,流程应该是这样的:js 通过 javascriptChannel 的方法向 flutter 请求数据,由 js 把数据写入 LocalStorage。这样我们可以保持一定的灵活性,比如修改为把数据写入数据库也是很容易的。

cookie 另外一个主要用途是跟踪分析用户。P3P 可以跨域设置 cookie,了解下即可。

番外

周五接到通知,周六日要开会。我想这下写文的计划是不成了。但是无巧不成书,周五下午就开始不舒服,晚上没吃饭,头痛。周六起来后更严重了,我只好请假。我也很无奈啊,早不病,晚不病,正好赶上开会,怎么这么巧呢,这样很容易让人误会我在找理由躲避开会。但是考虑到我自己健康,我还是决定在家休息。没有胃口,要去开会的话,这一天吃什么,在家里,我准备了耙耙柑,猕猴桃,苹果和梨。感冒的时候,我只想吃这些。今天周一了还没见有好转的迹象。鼻塞,要用嘴呼吸,浑身无力,有些头痛。好在家里随时可以躺下来,状态好的时候起来写文,于是这篇 《Flutter WebView 如何与 h5 同步登录状态》还是如约而至了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python|每日一练|动态规划|图算法|散列表|数组|双指针|单选记录:不同路径|求两个给定正整数的最大公约数和最小公倍数|删除有序数组中的重复项

1、不同路径&#xff08;数学&#xff0c;动态规划&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”…

【大数据基础】Linux常用命令

参考资料&#xff1a; https://www.runoob.com/w3cnote/linux-common-command-2.html 1、ls命令 就是 list 的缩写&#xff0c;通过 ls 命令不仅可以查看 linux 文件夹包含的文件&#xff0c;而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息等等。 ls -a 列…

LockSupport常用方法源码分析

前言&#xff1a;本文将介绍LockSupport类中的方法和部分源码&#xff0c;以及面试常问到的一个小问题&#xff0c;感兴趣的大佬可以指点下。 希望能够加深自己的印象以及帮助到其他的小伙伴儿们&#x1f609;&#x1f609;。 如果文章有什么需要改进的地方还请大佬不吝赐教&am…

uniapp项目引入vant2遇到报错Uncaught ReferenceError: require is not defined完美解决方案

一、问题描述 我用的是Vue2版本的uniapp项目&#xff0c;以下是Vant官方提供的安装方法&#xff0c;使用npm安装到uniapp项目中。 Vant官网&#xff1a;https://vant-contrib.gitee.io/vant/v2/#/zh-CN/quickstart 安装完成得到以下模块 官方提供的引入单个组件的方案 我需要引…

Vision Transformer(ViT) 2: 应用及代码讲解

文章目录1. 代码讲解1.1 PatchEmbed类1&#xff09;__init__ 函数2) forward 过程1.2 Attention类1&#xff09;__init__ 函数2&#xff09;forward 过程1.3 MLP类1&#xff09;__init__ 函数2&#xff09;forward函数1.4 Block类1&#xff09;__init__ 函数2&#xff09;forwa…

MATLAB曲线拟合工具箱

MATLAB曲线拟合工具箱一、MATLAB曲线拟合工具箱1.导出拟合后的曲线数据2.调用m文件中的函数3.显示5位有效数字二、参考链接一、MATLAB曲线拟合工具箱 1.导出拟合后的曲线数据 生成代码后&#xff0c;默认函数名为createFit&#xff0c;可以自行修改&#xff0c;直接保存&#…

Allegro如何重命名光绘操作指导

Allegro如何重命名光绘操作指导 在做PCB设计的时候,光绘设置是输出生产文件必要的流程,设置好光绘之后,如何对光绘重新命名,如下图 如何把L1改成TOP,L6改成BOTTOM,具体操作步骤如下 点击Manufacture选择Artwork

每天一道大厂SQL题【Day11】微众银行真题实战(一)

每天一道大厂SQL题【Day11】微众银行真题实战(一) 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&…

【C++修炼之路】21.红黑树封装map和set

每一个不曾起舞的日子都是对生命的辜负 红黑树封装map和set前言一.改良红黑树的数据域结构1.1 改良后的结点1.2 改良后的类二. 封装的set和map2.1 set.h2.2 map.h三. 迭代器3.1 迭代器封装3.2 const迭代器四.完整代码实现4.1 RBTree.h4.2 set.h4.3 map.h4.4 Test.cpp前言 上一节…

epoll 笔记

maxevents 参数大小一般不超过64必须够了 maxevents 个事件&#xff0c;才会传到用户空间吗&#xff1f;可见&#xff0c;只要有事件就可以传到用户空间。一台服务器可以支撑多少个链接https://blog.csdn.net/mijichui2153/article/details/81331345 0、两台虚拟机的初始状态如…

数据库必知必会:TiDB(12)TiDB连接管理

数据库必知必会&#xff1a;TiDB&#xff08;12&#xff09;TiDB连接管理TiDB连接管理TiDB的连接特性连接TiDBMySQL命令行客户端图形界面客户端连接其他连接方式写在后面TiDB连接管理 TiDB的连接特性 TiDB Server主要负责接收用户的会话请求&#xff0c;接收SQL并负责SQL语句…

【2021/推荐/社交网络】Socially-Aware Self-Supervised Tri-Training for Recommendation

部分公式、图表和排版等显示可能异常,可在个人公众号(码农的科研笔记)进行全文免费阅读。 【2021/推荐/社交网络】Socially-Aware Self-Supervised Tri-Training for Recommendation 原文:https://dl.acm.org/doi/10.1145/3447548.3467340 源码:[伯乐 SEPT]、https://git…

Keychron K3 Pro键盘测评

目录 0.开箱 1.Keychron K3 Pro介绍 2.产品特点 2.1轻薄机身轴体解锁多场景办公 2.2 支持QMK/VIA开源改键蓝牙/有线双模客制化机械键盘 ​2.3支持MacOS/Windows系统秒切换不卡顿 2.4同时适配3台设备可快速切换 ​2.5支持QMK/VIA改键 2.6 超轻薄佳达隆矮轴,触感新体验 …

ChatGPT火爆来袭,携手参与为开源助力

前言&#xff1a; Hello大家好&#xff0c;我是Dream 。最近语言模型ChatGPT在网络上一阵大火&#xff0c;ChatGPT 以惊人的速度问世&#xff0c;在技术圈中引起了广泛讨论。在 GitHub 上近期还诞生了多个 ChatGPT 相关的开源项目&#xff0c;数量之多令人瞠目结舌&#xff0c;…

LeetCode142 环形链表Ⅱ

题目&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评…

软考高级-信息系统管理师之人力资源管理(最新版)

人力资源管理目录 项目人力资源管理项目人力资源管理概念项目团队项目管理团队领导和管理冲突和竞争项目人力资源管理过程规划项目人力资源管理组建项目团队建设项目团队管理项目团队项目人力资源管理工具虚拟团队集中办公团队发展阶段人际关系技能权力冲突管理激励理论X理论和…

【python】数据分析案例

目录 一、项目内容&#xff1a; 第一步&#xff1a;获取评论数据 第二步&#xff1a;词频统计并可视化展示 第三步&#xff1a;绘制词云 二、项目实现&#xff1a; 第一步&#xff1a;获取评论数据 &#xff08;1&#xff09;导入python库 &#xff08;2&#xff09;获…

煤矿风险监测预警算法 YOLO

煤矿风险监测预警算法基于YOLO网络模型视觉分析&#xff0c;煤矿风险监测预警算法7*24小时不间断自动识别现场人员作业行为、着装合规情况以及传送皮带撕裂跑偏等风险异常情况。我们使用YOLO(你只看一次)算法进行对象检测。YOLO是一个聪明的卷积神经网络(CNN)&#xff0c;用于实…

Hive 2.3.0 安装部署(mysql 8.0)

Hive安装部署 一.Hive的安装 1、下载apache-hive-2.3.0-bin.tar.gz 可以自行下载其他版本&#xff1a;http://mirror.bit.edu.cn/apache/hive/ 2.3.0版本链接&#xff1a;https://pan.baidu.com/s/18NNVdfOeuQzhnOHVcFpnSw 提取码&#xff1a;xc2u 2、用mobaxterm或者其他连接…

【拦截器、过滤器、springAop】那些不为人知的隐秘

首先说到这几个词的时候&#xff0c;大家肯定都很熟悉了&#xff0c;甚至觉得这几个的区别刚刚毕业都能回答了&#xff0c;但是我想大家在实际应用过程中是真得会真正的使用吗&#xff1f;换言之&#xff0c;什么时候用过滤器什么时候使用拦截器&#xff0c;什么时候使用spring…