springboot 解决跨域问题

处理前后端分离中的跨域问题

协议域名端口中有一个不一样就属于不同的域。因浏览器的同源策略,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);
	}
}

你可能感兴趣的:(Java,Web,spring,boot,跨域)