谈一谈 拦截器和跨域问题
一、为什么会出现跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
二、什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域图片
java 后端 实现 CORS 跨域请求的方式
对于 CORS的跨域请求,主要有以下几种方式可供选择:
1.返回新的CorsFilter
2.重写 WebMvcConfigurer (用的多)
3.使用注解 @CrossOrigin
4.手动设置响应头 (HttpServletResponse)
5.自定web filter 实现跨域 (用的多)
在前后端分离项目盛行下,跨域问题肯定会存在的。我们一般在后端进行跨域处理
使用自定义filter实现跨域:
package com.zyw.shows.config;
import org.springframework.stereotype.Component;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Date: 2021-01-05
* @Author: zyw
* @Description:跨域配置
*/
@Component
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin"));
httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
拦截器基本配置类如下
自定义拦截器
package com.zyw.shows.config;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author zyw
* 拦截器
*/
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
try {
// 后续登录判断返回前端错误
JSONObject res = new JSONObject();
res.put("success", "false");
res.put("code", "403");
res.put("msg", "访问无权限-拦截");
return true;
} catch (Exception ex) {
response.sendError(500);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("================= jin ru after ===============");
}
}
拦截器配置
package com.zyw.shows.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author zyw
* 拦截器
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static/login.html");
}
// @Override
// public void addCorsMappings(CorsRegistry registry) { // 不能写在一起否则报冲突 需要用filter过滤器去解决跨域问题
// registry.addMapping("/**")
// .allowedOrigins("*")
// .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
// .maxAge(3600)
// .allowCredentials(true);
// }
}
至于拦截器里面具体业务代码 后续我们通过具体案例来谈一谈 登录拦截/权限拦截等等。
返回新的 CorsFilter(全局跨域)
在任意配置类,返回一个 新的 CorsFIlter Bean ,并添加映射路径和具体的CORS配置路径。
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1. 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送 Cookie
config.setAllowCredentials(true);
//放行哪些请求方式
config.addAllowedMethod("*");
//放行哪些原始请求头部信息
config.addAllowedHeader("*");
//暴露哪些头部信息
config.addExposedHeader("*");
//2. 添加映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",config);
//3. 返回新的CorsFilter
return new CorsFilter(corsConfigurationSource);
}
}
- 重写 WebMvcConfigurer(全局跨域)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//放行哪些原始域
.allowedOrigins("*")
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
}