处理前后端分离中的跨域问题
协议
、域名
、端口
中有一个不一样就属于不同的域。因浏览器的同源策略,A域的页面上通过ajax调用域B的接口就会出现跨域问题,调用失败。
普通的springboot工程解决跨域问题
spring提供了一个CorsFilter
可以专门用来处理跨域问题。可以直接在启动类配置:
启动类本身就是一个配置类,这里就不单独创建配置类了。
@Bean
public FilterRegistrationBean corsFilterBean() {
FilterRegistrationBean filterBean = new FilterRegistrationBean();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://localhost:8080");// 允许哪些域进行跨域访问
corsConfiguration.addAllowedMethod("GET");// 允许的请求方式
corsConfiguration.addAllowedMethod("POST");
corsConfiguration.addAllowedHeader("Content-Type");// 允许的请求头
corsConfiguration.setAllowCredentials(false);// 是否允许携带cookie
// 导包时要导入org.springframework.web.cors包下的。不能用org.springframework.web.cors.reactive包下的。
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);// 配置拦截路径,所有的请求都会被处理
CorsFilter corsFilter = new CorsFilter(corsConfigurationSource);
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(corsFilter);
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
前后端分离&用springsecurity的springboot工程解决跨域问题
假设这是前后端分离项目,前端通过ajax访问后端接口,那么用spring security之后,在后端要做认证和授权,如果没登陆或没权限,就会被相应的过滤器给逮住,认证和授权时可以实现响应接口做自定义配置。假设这里配置了两个类,认证失败时进入NoLoginHandler,授权失败时进入NoAuthHandler。所以如果自定义配置的话,在这两个过滤器里也要解决跨域问题。
在上面的FilterRegistrationBean
配置基础上,由于我们自定义了异常处理的handler,所以在这两个handler中也要添加跨域的请求头,因为走到跨域相关的过滤器前,由于用户没登陆或没权限,而用spring security时大部分的接口都要做权限校验,所以没登陆或没权限时,直接走到了NoLoginHandler或NoAuthHandler中,但在这两个过滤器里面还没有允许跨域。所以各个加允许跨域就行:
/config/NoLoginHandler.java
public class NoLoginHandler implements AuthenticationEntryPoint{
@Override
public void commence(HttpServletRequest request,HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
// 后端给前端返回json数据
// 构造json数据
Map<String,String> map = new HashMap<>();
map.put("code", "401");// 没登陆一般是401
map.put("message", "未登录");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
response.setHeader("Access-Control-Request-Method", "GET,POST");
response.setHeader("Access-Control-Request-Headers","Content-Type");
response.getWriter().print(json);
}
}
/config/NoAuthHandler.java
public class NoAuthHandler implements AccessDeniedHandler{
@Override
public void handle(HttpServletRequest reqeust, HttpServletResponse response,AccessDeniedException accessDeniedException)
throws IOException, ServletException {
// 跟没登陆时一样,在没权限时,在这里返回json数据就行
// 后端给前端返回json数据
// 构造json数据
Map<String,String> map = new HashMap<>();
map.put("code", "403");// 没权限一般是403
map.put("message", "没权限");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
response.setHeader("Access-Control-Request-Method", "GET,POST");
response.setHeader("Access-Control-Request-Headers","Content-Type");
response.getWriter().print(json);
}
}