前后端分离的项目,浏览器发送请求给服务器通常都要发送两次,
其中一次是options类型的请求,可打开network查看,主要是为了验证服务器是否可用,而options请求又不会携带我们自定义的header数据,所以必然会被拦截器给拦截,导致二次请求失败,因此对于options类型的请求必须无条件放行

  if (request.getMethod().equals("OPTIONS")) {
            return true;
        }

现在options请求可以通过,但是无法获取session里面的数据,而在登录成功时明明把用户数据放进了session里,可取出来时为null,这是因为前后端分离的项目每次请求的sessionid都不同,所以取不出来数据,原因如下:
在前后端分离的项目中,浏览器第一次访问服务器时,在响应头中会包含set-cookie,里面放置着JSESSIONID,浏览器则会将JSESSIONID设置到Cookies中保存。当浏览器再次发送请求到服务器时,会在请求头中携带cookie信息,其内容即为JSESSIONID。当用户访问服务器的时候会为每一个用户开启一个session,JSESSIONID就是被用来判断当前用户对应于哪个session的。
解决sessionid不一致的问题方法

axios.defaults.withCredentials = true

现在options请求验证的问题解决了,sessionid不同的问题也解决了,但还是不行,那是因为跨域的问题,可我已经在controller中配置了@CrossOrigin注解,最后发现在controller中配置跨域并不能解决拦截器的跨域问题,所以最后增加了统一配置

package com.oa.config;

import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class Myconfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/login","/user/logout");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders(CorsConfiguration.ALL)
                .allowedMethods(CorsConfiguration.ALL)
                .allowCredentials(true)
                .maxAge(3600); // 1小时内不需要再预检(发OPTIONS请求)
    }
}

这样所有的问题就解决了,一共3步。完整代码如下
拦截器类

package com.oa.config;

import com.oa.enums.CommonEnum;
import com.oa.exception.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

@Component
@Slf4j
public class MyInterceptor implements  HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getMethod().equals("OPTIONS")) {
            return true;
        }
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            throw new CommonException(CommonEnum.USER_NOT_LOGIN);
        }
        Object user = request.getSession().getAttribute(token);
        log.info("拦截器token={},user={}",token,user);
        if (user == null) {
            throw new CommonException(CommonEnum.USER_NOT_LOGIN);
        }else {
            return true;
        }
    }

}

配置类

package com.oa.config;

import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class Myconfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/login","/user/logout");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders(CorsConfiguration.ALL)
                .allowedMethods(CorsConfiguration.ALL)
                .allowCredentials(true)
                .maxAge(3600); // 1小时内不需要再预检(发OPTIONS请求)
    }
}

Logo

前往低代码交流专区

更多推荐