钱塘江上潮信来 今日方知我是我.|

Appletree24

园龄:2年11个月粉丝:25关注:0

2022-10-05 16:53阅读: 687评论: 0推荐: 0

记一次SpringBoot中跨域的小问题

记一次SpringBoot中跨域的小问题

问题

前阵子,有个学长在跨域的时候遇到一个问题,我们两个人互相讨论了一番,得到了问题的答案。问题如下:

PXeTS.png

如果按照上图的方式配置跨域类,那么就会出现报403的问题,我把我的配置类发给学长后,果然是没问题了,那么看来问题就出在两个配置类里不一样的地方了

PXQZF.png

解决方式

对比两张图中的配置,可以发现出在了allowedOrigin.allowedOriginPatterns这两个方法上,于是乎我到官方文档上查阅了这两个方法的详细介绍,得到了如下内容:

PYGNs.png

PYCa0.png

现在终于恍然大悟了,文档里都介绍的很清楚了。但是知道了解决方式以后,我去看了一下源码,了解一下到底为什么可以这么做.

源码+相关内容

PYKX5.png

config变量是CorsConfiguration的一个实例化对象。那么看来这两个方法的区别要更深一层,同样是点进去看一下,先看第一个。

PYXYw.png

入参是可以为空的字符串列表,判空之后对非空情况进行一个常见的处理,使用的是函数式编程,其中有一个名为trimTrailingSlash的方法,这个看名字应该是和MySQL里的trim差不多的,点进去看一下

PnLBo.png

果不其然,作用是去掉传入URL最后的一个/。到这里这个方法就全部结束了,看着也太简单了,果然是被抛弃了的一个方法

PnOey.png

上图是第二个方法的内容,同样入参一个可以为空的字符串列表,关键在于这个addAllowedOriginPattern方法,继续点进去看

Pn4tU.png

入参为字符串类型的originPattern,这里就体现出来一个setAllowedOriginPatterns的好处了,如果我们传入了多个需要跨域的格式,那么MVC会帮我们挨个进行处理,调用trimTrailingSlash方法进行/的剔除。看到这里,你可能会有些疑惑,这样看来两个方法不是没什么区别吗?是的,如果看到这里,那确实没啥区别,但是真正的区别其实是下面这个:

PnSHN.png

allowedOrigins是给setAllowedOrigin用的,可以看到列表中的元素类型为String类,那么下面这个allowedOriginPatterns是给setAllowedOriginPatterns用的,列表内容是OriginPattern类,这个类从来没听过,而且一看名字就知道是Spring自己写的,所以我们继续点进去看。

PnH5C.png

类里有一个字符串,两个正则,那肯定两个正则是处理这个字符串的。构造方法OriginPattern,初始化正则格式。这个正则还是很好看懂的,\E和\Q转义出来其实就是要匹配*这个字符,这也就是为什么setAllowedOriginPatterns在官方文档中介绍说可以在传入跨域格式的字符串中填写*号,而不用是已经完全确定的一个格式。


关于CORS中Access-Control-Allow-Origin这个header,规定我们只能设置为如下三种情况:

  • 单域名
  • none

同时如果我们设置为了*,那么Access-Control-Allow-Credentials就不能设置为true了。跨源资源共享(CORS) - HTTP | MDN (mozilla.org)

基于以上的规则,我们总结一下:如果我们需要发送Cookie,那么前端需要设置withCredentials为true,且同时后端也要设置Access-Control-Allow-Credentials为true,并且Access-Control-Allow-Credentials不能设置为*,只能为单域名

但是这时候就又出现一个问题,我的跨域配置类中,withCredentials传参是*啊,而且也不是单域名,为什么跨域还是成功了呢?学了这么长时间的Spring,我多少有个猜测——肯定也是有个很牛逼的东西帮我处理了这个问题

@Nullable
public String checkOrigin(@Nullable String origin) {
if (!StringUtils.hasText(origin)) {
return null;
} else {
String originToCheck = this.trimTrailingSlash(origin);
Iterator var3;
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
if (this.allowedOrigins.contains("*")) {
this.validateAllowCredentials();
return "*";
}
var3 = this.allowedOrigins.iterator();
while(var3.hasNext()) {
String allowedOrigin = (String)var3.next();
if (originToCheck.equalsIgnoreCase(allowedOrigin)) {
return origin;
}
}
}
if (!ObjectUtils.isEmpty(this.allowedOriginPatterns)) {
var3 = this.allowedOriginPatterns.iterator();
while(var3.hasNext()) {
OriginPattern p = (OriginPattern)var3.next();
if (p.getDeclaredPattern().equals("*") || p.getPattern().matcher(originToCheck).matches()) {
return origin;
}
}
}
return null;
}
}

果不其然,我找到了这个名为checkOrigin的方法,内容中明确写道。如果我们同时将credentials设置为true且allowedPatterns为*,那么这个方法就会把Access-Control=Allow-Origin设置为当前请求过来的origin,也就解决了这个问题。

本文作者:Appletree24

本文链接:https://www.cnblogs.com/appletree24/p/16755853.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Appletree24  阅读(687)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 愛錠 (Edit ver.) LiSA
愛錠 (Edit ver.) - LiSA
00:00 / 00:00
An audio error has occurred.

話してしまえば 思い出

隠してしまえば 幸せ

時間がすべてを奪ってく

What do you think?do you think?

愛してしまえば 地獄で

離れてしまえば 孤独だ

もう戻れない

ああ、想う 想うほど 絡まる愛錠

この手を繋ぐ鎖のように

ただ目の前の明日を信じられるのならば

それだけでいい

今そっと手を伸ばした

もたれてしまえば 2倍で

壊してしまえば それぞれ

時間このまま過ぎ去って

What do you think?do you think?

願ってしまえば 欲しくて

叶ってしまえば 足りない

知っている

もう戻れはしない

あの日には

今夜すべてを置き去りに

独りで逃げ出したって

きっと私はいつまでも

後悔に縛られたまま

ずっときょうを恨みながら

罪責と悪夢に魘されるのでしょう

解けないわ

鉄と鉄が擦れ合い

指と指の温もりも

今ここに貴方を感じられるカギ

ああ、想う 想うほど 絡まる愛錠

この手を繋ぐ鎖のように

ただ目の前の明日を信じられるのならば

それだけでいいよ 今は

ああ、巡る 巡るほど 絡まる愛錠

切れない絆 確かめながら

どんな見えない明日も貴方が傍にいるのなら

それだけでいい

強く確かな愛情