spring跨域(iframe访问页面)

线上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;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现iframe跨域访问页面,需要满足以下条件: 1. 父页面和子页面都是自己可以控制的。 2. 被嵌入的页面不属于同一个域名、协议或端口号的源。 实现iframe跨域访问页面可以采用以下方法: 1. 使用postMessage:通过在父页面和子页面之间进行消息传递,可以安全地实现跨域通信。父页面可以使用`window.postMessage()`方法向子页面发送消息,子页面可以通过监听`message`事件接收并处理这些消息。这种方式允许双向通信,并且在不同的窗口间传递数据时更加安全可靠。 2. 设置document.domain:如果父页面和子页面具有相同的顶级域名,但不同的子域名,可以通过设置相同的document.domain来实现跨域访问。例如,如果父页面的域名是`example.com`,子页面的域名是`sub.example.com`,可以在父页面和子页面中都设置`document.domain = "example.com"`。这样,它们就可以进行跨域通信。 3. 使用CORS(跨域资源共享):在服务器端配置响应文件的HTTP头,允许来自其他域的页面访问。服务器需要设置特定的响应头,包括`Access-Control-Allow-Origin`来指定允许访问的域名。 总结起来,要实现iframe跨域访问页面,可以使用postMessage、设置document.domain或使用CORS来进行跨域通信。这些方法都可以确保安全地进行跨域访问,并实现在父页面和子页面之间的数据传递和通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值