线上B系统通过iframe的方式嵌入B系统的页面,结果报如下错误
最初网上查询得到的办法是加了如下过滤器
@WebFilter(filterName = "/corsFilter", urlPatterns = {"/*"})
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (res instanceof HttpServletResponse) {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Max-Age", "3600");
}
chain.doFilter(req, res);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
然而并没有用,后面在同事的提醒下在cookie上加上SameSite=None; Secure;防止浏览器拦截,因为用的spring security,所以设置了setSameSite(spring security若不设置SameSite,默认为lax类型),改成如下
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setSameSite(null);//加入的参数
serializer.setCookiePath("/");
serializer.setCookieMaxAge(604800);
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
自己这边测试浏览器可以访问嵌入的iframe了,但是同事那边不知道为什么还是不行,改成如下:
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setSameSite("None");//加入的参数
serializer.setUseSecureCookie(true);//加入的参数
serializer.setCookiePath("/");
serializer.setCookieMaxAge(604800);
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
然而还存在一个问题是,setUseSecureCookie参数只有在https才有效,http使用会出问题,所以判断请求是不是https来设置secure,具体实现如下,自定义CustomCookieSerializer继承DefaultCookieSerializer,重写writeCookieValue方法
import org.apache.commons.lang3.StringUtils;
import org.springframework.session.web.http.DefaultCookieSerializer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.BitSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomCookieSerializer extends DefaultCookieSerializer {
private static final BitSet domainValid = new BitSet(128);
static {
for (char c = '0'; c <= '9'; c++) {
domainValid.set(c);
}
for (char c = 'a'; c <= 'z'; c++) {
domainValid.set(c);
}
for (char c = 'A'; c <= 'Z'; c++) {
domainValid.set(c);
}
domainValid.set('.');
domainValid.set('-');
}
private Clock clock = Clock.systemUTC();
private String cookieName = "SESSION";
private Boolean useSecureCookie;
private boolean useHttpOnlyCookie = true;
private String cookiePath;
private Integer cookieMaxAge;
private String domainName;
private Pattern domainNamePattern;
private String jvmRoute;
private boolean useBase64Encoding = true;
private String rememberMeRequestAttribute;
private String sameSite = "None";
@Override
public void writeCookieValue(CookieValue cookieValue) {
HttpServletRequest request = cookieValue.getRequest();
HttpServletResponse response = cookieValue.getResponse();
StringBuilder sb = new StringBuilder();
sb.append(this.cookieName).append('=');
String value = getValue(cookieValue);
if (value != null && value.length() > 0) {
validateValue(value);
sb.append(value);
}
int maxAge = getMaxAge(cookieValue);
if (maxAge > -1) {
sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
ZonedDateTime expires = (maxAge != 0) ? ZonedDateTime.now(this.clock).plusSeconds(maxAge)
: Instant.EPOCH.atZone(ZoneOffset.UTC);
sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
}
String domain = getDomainName(request);
if (domain != null && domain.length() > 0) {
validateDomain(domain);
sb.append("; Domain=").append(domain);
}
String path = getCookiePath(request);
if (path != null && path.length() > 0) {
validatePath(path);
sb.append("; Path=").append(path);
}
if (this.useHttpOnlyCookie) {
sb.append("; HttpOnly");
}
//主要修改这个
String url = request.getRequestURL().toString();
if (StringUtils.isNotBlank(url) && url.startsWith("https")) {
sb.append("; SameSite=None; Secure");
}
response.addHeader("Set-Cookie", sb.toString());
}
/**
* Encode the value using Base64.
*
* @param value the String to Base64 encode
* @return the Base64 encoded value
* @since 1.2.2
*/
private String base64Encode(String value) {
byte[] encodedCookieBytes = Base64.getEncoder().encode(value.getBytes());
return new String(encodedCookieBytes);
}
private String getValue(CookieValue cookieValue) {
String requestedCookieValue = cookieValue.getCookieValue();
String actualCookieValue = requestedCookieValue;
if (this.jvmRoute != null) {
actualCookieValue = requestedCookieValue + this.jvmRoute;
}
if (this.useBase64Encoding) {
actualCookieValue = base64Encode(actualCookieValue);
}
return actualCookieValue;
}
private void validateValue(String value) {
int start = 0;
int end = value.length();
if ((end > 1) && (value.charAt(0) == '"') && (value.charAt(end - 1) == '"')) {
start = 1;
end--;
}
char[] chars = value.toCharArray();
for (int i = start; i < end; i++) {
char c = chars[i];
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) {
throw new IllegalArgumentException("Invalid character in cookie value: " + c);
}
}
}
private int getMaxAge(CookieValue cookieValue) {
int maxAge = cookieValue.getCookieMaxAge();
if (maxAge < 0) {
if (this.rememberMeRequestAttribute != null
&& cookieValue.getRequest().getAttribute(this.rememberMeRequestAttribute) != null) {
// the cookie is only written at time of session creation, so we rely on
// session expiration rather than cookie expiration if remember me is
// enabled
cookieValue.setCookieMaxAge(Integer.MAX_VALUE);
} else if (this.cookieMaxAge != null) {
cookieValue.setCookieMaxAge(this.cookieMaxAge);
}
}
return cookieValue.getCookieMaxAge();
}
private void validateDomain(String domain) {
int i = 0;
int cur = -1;
int prev;
char[] chars = domain.toCharArray();
while (i < chars.length) {
prev = cur;
cur = chars[i];
if (!domainValid.get(cur) || ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
|| (prev == '-' && cur == '.')) {
throw new IllegalArgumentException("Invalid cookie domain: " + domain);
}
i++;
}
if (cur == '.' || cur == '-') {
throw new IllegalArgumentException("Invalid cookie domain: " + domain);
}
}
private void validatePath(String path) {
for (char ch : path.toCharArray()) {
if (ch < 0x20 || ch > 0x7E || ch == ';') {
throw new IllegalArgumentException("Invalid cookie path: " + path);
}
}
}
private boolean isSecureCookie(HttpServletRequest request) {
if (this.useSecureCookie == null) {
return request.isSecure();
}
return this.useSecureCookie;
}
private String getDomainName(HttpServletRequest request) {
if (this.domainName != null) {
return this.domainName;
}
if (this.domainNamePattern != null) {
Matcher matcher = this.domainNamePattern.matcher(request.getServerName());
if (matcher.matches()) {
return matcher.group(1);
}
}
return null;
}
private String getCookiePath(HttpServletRequest request) {
if (this.cookiePath == null) {
return request.getContextPath() + "/";
}
return this.cookiePath;
}
}
@Bean
public CookieSerializer cookieSerializer() {
CustomCookieSerializer serializer = new CustomCookieSerializer();
return serializer;
}