说明:最近公司开发一款产品,前段使用js 后端使用springboot 期间调试接口的时候会出现跨域问题,及解决之后又遇到的问题,
1:接口调试的时候遇到的问题,前段访问我的接口,存在跨域:
表现为:
表明存在跨域行为;
解决:使用拦截器进行解决:
①:定义一个拦截器实现handlerInterceptor
@Component public class CorsInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse response, Object o) throws Exception { response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); response.addHeader("Access-Control-Max-Age", "3600"); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
②:设置拦截请求的路径,这里对所有的请求进行拦截;
@Configuration public class MonitorInterceptor extends WebMvcConfigurerAdapter { private CorsInterceptor corsInterceptor; private LoginInterceptor loginInterceptor; @Autowired public MonitorInterceptor(CorsInterceptor corsInterceptor, LoginInterceptor loginInterceptor) { this.corsInterceptor = corsInterceptor; this.loginInterceptor = loginInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { super.addInterceptors(registry); registry.addInterceptor(corsInterceptor).addPathPatterns("/v1/**"); // registry.addInterceptor(corsInterceptor).addPathPatterns("/v2/**"); // registry.addInterceptor(loginInterceptor).addPathPatterns("/v1/**"); // registry.addInterceptor(loginInterceptor).excludePathPatterns("/v2/**"); }
通过以上方式即可实现跨域问题,但是业务中存在登录验证功能,也就是对于对应的功能,如果没有登录,不能访问数据
这里我还是通过拦截器进行操作的;代码如下:
@Configuration public class MonitorInterceptor extends WebMvcConfigurerAdapter { private CorsInterceptor corsInterceptor; private LoginInterceptor loginInterceptor; @Autowired public MonitorInterceptor(CorsInterceptor corsInterceptor, LoginInterceptor loginInterceptor) { this.corsInterceptor = corsInterceptor; this.loginInterceptor = loginInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { super.addInterceptors(registry); registry.addInterceptor(corsInterceptor).addPathPatterns("/v1/**"); registry.addInterceptor(corsInterceptor).addPathPatterns("/v2/**"); registry.addInterceptor(loginInterceptor).addPathPatterns("/v1/**");//添加拦截路径, registry.addInterceptor(loginInterceptor).excludePathPatterns("/v2/**");//将登录请求的路径释放,即不进行拦截 }
@Component public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { // httpServletResponse.setHeader("Accessx-Control-Allow-Origin", "*"); // httpServletResponse.setHeader("Access-Control-Allow-Headers", "Authorization"); UserDTO user = (UserDTO) httpServletRequest.getSession().getAttribute("user"); if (user == null) { httpServletResponse.getOutputStream().print(BaseStatusEnums.NOT_AUTHORITY.getTag()); return false; } return true; }
这里通过验证获取sessio来判断是否有该用户,当然在登录的时候我将用户信息放到session中,如下:
if (userDTO != null) { request.getSession().setAttribute("user", userDTO); return new ResponseEntity<>(new BasicResult<>(true, "登录成功", userDTO, 0), HttpStatus.OK); }
可是;这种情况下sessionid是变化的;可通过断点查看和前段中cookie中是否一样
这时候出现的问题就是传说的session跨域问题
@Component public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //添加拦截放在这里 httpServletResponse.setHeader("Accessx-Control-Allow-Origin", "*"); httpServletResponse.setHeader("Access-Control-Allow-Headers", "Authorization"); UserDTO user = (UserDTO) httpServletRequest.getSession().getAttribute("user"); if (user == null) { httpServletResponse.getOutputStream().print(BaseStatusEnums.NOT_AUTHORITY.getTag()); return false; } return true; }
@Configuration public class MonitorInterceptor extends WebMvcConfigurerAdapter { private CorsInterceptor corsInterceptor; private LoginInterceptor loginInterceptor; @Autowired public MonitorInterceptor(CorsInterceptor corsInterceptor, LoginInterceptor loginInterceptor) { this.corsInterceptor = corsInterceptor; this.loginInterceptor = loginInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { super.addInterceptors(registry); //这里去掉,注意和前面对比 // registry.addInterceptor(corsInterceptor).addPathPatterns("/v1/**"); // registry.addInterceptor(corsInterceptor).addPathPatterns("/v2/**"); registry.addInterceptor(loginInterceptor).addPathPatterns("/v1/**"); registry.addInterceptor(loginInterceptor).excludePathPatterns("/v2/**"); }
前段需要对应的操作:
$.ajax({ url: host + $("#submitData").attr("action"), type: $("#submitData").attr("method"), data: $("#submitData").serialize(), dataType: "json", //每个ajax请求都需要加上这个 xhrFields: { withCredentials: true }, async: isAsync, success: function (data) { sh(data);这样的话就解决了跨域问题,但是也存在一个问题,就是如果用户没有登录去访问页面,页面也会报跨域问题,如果用户在登录状态去访问,那么就可以正常使用,不报错误!希望网友看到好的解决方法,能够一起进步,欢迎留言讨论