后端ssm 前端ajax 跨域问题解决与引起的新的问题多次请求的sessionId不同

后端

跨域代码

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author jjl
 * @create 2020-05-08 10:29
 */

public class SimpleCORSFilter implements Filter {
    private boolean isCross = false;

    public void destroy() {
        isCross = false;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (isCross) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            System.out.println("拦截请求: " + httpServletRequest.getServletPath());
            httpServletResponse.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
            httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            httpServletResponse.setHeader("Access-Control-Max-Age", "0");
            httpServletResponse.setHeader("Access-Control-Allow-Headers",
                    "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpServletResponse.setHeader("XDomainRequestAllowed", "1");
        }
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        String isCrossStr = filterConfig.getInitParameter("IsCross");
        isCross = isCrossStr.equals("true") ? true : false;
        System.out.println(isCrossStr);
    }
}

配置springMVC.xml

其它配置省略

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
 <!--     其它配置省略-->
 <!--     接口跨域配置-->
    <mvc:cors>
        <mvc:mapping path="/**"  allowed-origins="*"
                     allowed-methods="POST, GET, OPTIONS, DELETE, PUT"
                     allowed-headers="Content-Type,  Content-Length, Authorization, Accept, X-Requested-With, yourHeaderFeild"
                     allow-credentials="true" />
    </mvc:cors>
    
</beans>

前端ajax

xhrFields: { withCredentials: true },
crossDomain: true

$.ajax({
        type:type,
        url:baseUrl+url,
        data: JSON.stringify(data),
        //关闭默认的contentType(默认的形式是表单)
        contentType: false,
        /设置新的contentType
        contentType:'application/json; charset=utf-8',
        //预期服务器返回数据的类型
        dataType: 'json',  
        xhrFields: { withCredentials: true },
        crossDomain: true,
        success:function(data){
        },
        error:function(jqXHR){ 
        }
});

如果只是这里是可以解决跨域的,但是chrome 浏览器会因其新的问题 就是多次请求的sessionId 不一样

解决办法如下:

Chrome升级到80版本之后cookie的SameSite属性默认值由None变为Lax,这也就造成了一些访问跨域cookie无法携带的问题。
解决:
打开谷歌浏览器在Chrome中访问chrome://flags/,搜索SameSite并设置为disabled即可。

在这里插入图片描述

到目前为止跨域与多次请求session不一致的问题就解决了

<think>好的,我现在需要解决用户在纯SSM项目中使用@CrossOrigin注解导致后端获取HttpSession不一致的问题。首先,我得理解用户的问题场景。用户可能在请求时,虽然前端后端已经配置了允许和携带凭证,但服务器端接收到的session不一致,导致无法正确维持会话状态。 首先,我需要回顾请求session管理的基本机制。当浏览器发起请求时,如果涉及到身份验证或会话,通常需要设置withCredentials为true来携带cookie。而后端也需要配置允许源和携带凭证。根据用户提供的引用[1]和[2],用户已经在Controller上使用了@CrossOrigin注解,并设置了allowCredentials="true",但依然出现session不一致的问题。这可能意味着虽然配置正确,但服务器在处理请求时未能正确识别或维持同一个session。 接下来,我需要考虑可能的原因。首先,请求时,如果后端没有正确配置允许的源,或者多个源存在,可能导致session不一致。例如,如果前端来自不同名或端口,服务器可能每次生成新的session。用户示例中的origin设置为http://localhost:8081,但实际可能有其他情况。 然后,检查@CrossOrigin注解的使用是否正确。在SSM框架中,该注解通常用于Spring MVC的Controller类或方法级别,用来指定允许的源、方法、头部等。需要确认是否所有相关的Controller都正确配置了相同的origin,并且allowCredentials设置为"true"。如果某些请求未被注解覆盖,可能导致部分请求未能正确携带session信息。 另外,考虑CORS过滤器的配置。虽然用户提到的是纯SSM项目,但可能除了注解方式,还需要全局的CORS配置。例如,在web.xml中添加CORS过滤器,或者在Spring的配置文件中进行全局设置。有时候,注解和过滤器同时存在可能导致配置冲突,需要检查是否有其他过滤器干扰了session的处理。 还要注意SameSite属性的影响。现代浏览器对cookie的SameSite属性有默认限制,如果没有显式设置,可能会导致请求时cookie不被发送。虽然这通常在前端设置,但后端可能需要确保session cookie的SameSite属性为None,并且Secure(如果使用HTTPS)。不过,用户项目是纯SSM,可能使用的是HTTP,这时候需要确认浏览器的安全策略是否允许。 此外,检查session的存储和生成机制。是否在请求时,服务器端由于某些原因(如不同名或端口)生成了新的session ID。可能需要确保服务器正确识别来自同一客户端的请求,并关联到同一个session解决方案方面,可能需要以下几点: 1. 确保所有相关的Controller都正确配置了@CrossOrigin,包括一致的origin和allowCredentials。 2. 添加全局CORS配置,确保所有请求路径都应用设置,避免遗漏。 3. 在web.xml中配置CORS过滤器,处理OPTIONS预检请求,并允许携带凭证。 4. 检查前端请求是否正确设置withCredentials为true,例如在使用XMLHttpRequest或fetch时明确指定。 5. 确保服务器端的session配置正确,例如session的超时时间,以及cookie的路径和设置。 6. 验证浏览器是否发送了正确的cookie,可以通过开发者工具查看请求头中的Cookie字段。 最后,可能需要测试不同的配置组合,逐步排查问题所在。例如,先确保全局CORS配置正确,再检查前端请求设置,最后验证session的管理是否正常。如果问题依旧存在,可能需要查看服务器日志,确认session的创建和获取过程,或者使用工具如Postman模拟请求,排除前端代码的影响。</think>在纯SSM框架中解决`@CrossOrigin`注解导致的HttpSession不一致问题,需重点关注配置Session管理的协同工作。以下是分步解决方案: --- ### 一、核心问题定位 请求时浏览器的安全策略会阻止携带凭证(如Cookie/SessionID),导致: 1. 预检请求(OPTIONS)未携带SessionID,触发服务端创建新Session 2. 实际请求(GET/POST)使用新SessionID服务端已有Session不一致[^1] --- ### 二、关键配置步骤 #### 1. 后端全局配置(Spring MVC) 在`spring-mvc.xml`中添加全局配置,避免注解覆盖不全: ```xml <mvc:cors> <mvc:mapping path="/**" allowed-origins="http://localhost:8081" allowed-methods="GET,POST,PUT,DELETE" allowed-headers="*" allow-credentials="true" max-age="3600"/> </mvc:cors> ``` #### 2. 强制SessionID传递 在`web.xml`中添加过滤器,处理OPTIONS预检请求SessionID: ```xml <filter> <filter-name>cors</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.support.credentials</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>cors</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ``` #### 3. 会话Cookie加固 在`web.xml`中配置会话Cookie属性: ```xml <session-config> <cookie-config> <http-only>true</http-only> <secure>false</secure> <!-- 本地开发设为false --> <same-site>None</same-site> </cookie-config> <session-timeout>30</session-timeout> </session-config> ``` --- ### 三、前端关键配置 1. AJAX请求必须携带凭证: ```javascript axios.defaults.withCredentials = true ``` 2. 确保请求头包含: ```http Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: Set-Cookie ``` --- ### 四、验证方案 1. **预检请求验证**:观察Chrome DevTools中OPTIONS请求是否返回: ```http Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:8081 ``` 2. **Session一致性验证**: ```java @RequestMapping("/checkSession") @ResponseBody public String checkSession(HttpServletRequest request) { return request.getSession().getId(); // 多次请求返回相同ID即成功 } ``` --- ### 五、典型问题排查 | 现象 | 解决方案 | |---------------------|---------------------------------| | 每次请求创建新Session | 检查OPTIONS请求是否跳过Session管理 | | Cookie未保存 | 确认前端`allowed-origins`完全一致 | | 401未授权错误 | 确保`allowed-headers`包含Authorization | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值