說明:最近公司開發一款產品,前段使用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);這樣的話就解決了跨域問題,但是也存在一個問題,就是如果用戶沒有登錄去訪問頁面,頁面也會報跨域問題,如果用戶在登錄狀態去訪問,那麼就可以正常使用,不報錯誤!希望網友看到好的解決方法,能夠一起進步,歡迎留言討論