跨域请求每次请求都是新的回话导致Session不同的问题

1.发现问题

刚学完vue2自己做了一个前段项目练练手,但是没有学vue2的反向代理

我遇到这个问题就是因为在后端为了实现createTime createBy updateTime updateBy等字段的自动填充,自己写了连个类
一个是MyMetaObjectHandler

package com.viego.financialrecommendsystem.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * 源数据处理器
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入自动填充
     * @param metaObject 填充对象
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        Long currentId = BaseContext.getCurrentId();
        log.info("公共字段自动填充中【insert】");
        log.info(metaObject.toString());
        log.info("已从BaseContext中获取到当前的UID,UID = {}",currentId);
        metaObject.setValue("updateTime", new Date());
        metaObject.setValue("updateBy",currentId);
        metaObject.setValue("createTime",new Date());
        metaObject.setValue("createBy",currentId);
    }

    /**
     * 更新自动填充
     * @param metaObject 填充对象
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        Long currentId = BaseContext.getCurrentId();
        log.info("公共字段自动填充中【update】");
        log.info(metaObject.toString());
        log.info("已从BaseContext中获取当前的UID,UID={}",currentId);
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateBy",currentId);
    }
}

其次还有一个BaseContext类

package com.viego.financialrecommendsystem.common;

/**
 * 基于ThreadLocal封装的工具类,用户保存或获取当前登录用户的ID
 */
public class BaseContext {

    private static ThreadLocal<Long> threadLocal=new InheritableThreadLocal<>();

    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

因为用到了这个Thread线程所以,我们需要使用过滤器,Filter

之后我又写了一个过滤器

package com.viego.financialrecommendsystem.filter;

import com.alibaba.druid.support.json.JSONUtils;
import com.viego.financialrecommendsystem.common.AjaxResult;
import com.viego.financialrecommendsystem.common.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

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

/**
 * 检查用户是否应完成登录的过滤器
 */
// urlPatterns="/*"表示次拦截器,要眼界所有路径的请求
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    //路径配置器,支持通配符
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        log.info("拦截到请求:{}",request.getRequestURI());
        /**
         * 1.获取本次请求的URL
         * 2.判断你本次请求是否需要处理
         * 3.如果不需要处理,则直接放行
         * 4.判断登录状态,如果已经登录,则放行
         * 5.如果未登录,则返回未登录的结果
         */
        //1.获取本次请求
        String requestURI = request.getRequestURI();
        String[] urls = {
            "/FinancialRecommend/user/login",
            "/FinancialRecommend/user/logout",
                "/FinancialRecommend/img/**",
        };
        //2.判断本次请求是否需要处理
        boolean check = check(urls, requestURI);
        //3.如果不需要处理,则直接放行
        if (check){
            //匹配成功,不需要不处理直接放行
            log.info("本次请求不需要处理:{}",requestURI);
            filterChain.doFilter(servletRequest,servletResponse);
        }else{
            //匹配失败,需要法处理,进行拦截
            log.info("本次请求需要处理:{}",request);
            Object uid = request.getSession().getAttribute("UID");
            if (uid != null){
                //用户已经登录直接放行
                log.info("已登录,放行");
                log.info("用户的 UID = {}",uid);
                BaseContext.setCurrentId((Long)uid );
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }else{
                //用户没有登录,通过输出流的燃放时,向前端返回数据
                log.info("用户未登录,向客户端返回NOTLOGIN");
                response.getWriter().write(JSONUtils.toJSONString(AjaxResult.error("NOTLOGIN")));
            }
        }
    }

    /**
     * 封装的静态方法
     * 判断请求是否需要处理
     * @param urls 需要处理的请求的数组
     * @param requestURI 当前请求的URL
     * @return 需要处理 true 不需要处理 false
     */
    public boolean check(String[] urls,String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match){
                //匹配成功
                return true;
            }
        }
        //匹配失败
        return false;
    }
}

2.思考问题

但是当我登录成功后,再次访问其他请求时,获取到的session都是和上次不一样,而在正常情况下,应该是一样的才对,可以拿出我登录时保存的UID,所以,问题在,为什么我每一次请求拿到的session都是不一样的,我接着继续思考。首先,我想到的一种情况就是,之前的session被销毁了,之后我就有自己设置了一下session的自动销毁时间,把所有的问题都拍出来,但是这个问题还是没有解决。

之后我就直接问的ChatGPT,

因为我这个项目是启动的两个服务,所以前段请求后端都是跨域请求,而如果前段不设置反向代理的话,每一次请求都是一次新的回话,也就是说,每一次请求的session都是不一样的,所以才导致了这个问题的产生,因此,我接着有在我的前端项目中做了一个反向代理

3.解决问题

下面是我的反向代理代码

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true
})
module.exports = {
  devServer: {
    proxy: {
      '/FinancialRecommend': {
        target: 'http://localhost:8888',//代理的目标地址
        changeOrigin: true,//是否改变请求源地址
        PathRewrite: {
          '^/FinancialRecommend': '/FinancialRecommend'//重写请求路径,将api代替为FinancialRecommend
        }
      }
    }
  }
}

加上这个代理了之后,我又在每一个组件中添加了这段代码

import axios from "axios";
axios.defaults.withCredentials = true

到了这个,这个问题也就解决了,因为我是第一次做这样的前后端分离项目,所以我也第一次做反向代理,我以前要做跨域请求的处理,都是在后端,因为我也更熟悉后端嘿嘿~~~

4.总结问题

在前后端分离的项目中,因为,前段和后端都是不通项目,所以会出现跨域请求的问题,这个问题该怎么解决,我们在前后端都需配置,前段需要看你用的什么框架(在这里我用的是Vue2)所以我就做了vue2的反向代理,然后后端就简单的做了一个,允许所有请求访问。至此,问题就都解决了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值