問題の原因
分離プロジェクトの終了前後に、フロントエンドとバックエンドのサービスは、単一のサーバーに展開することはできません。この場合は、フロントとリアエンドIPは一貫性がなくなります、それは多くの場合、前にクロスドメイン、ポートを作成し、プロジェクトの展開が終了した後、多くの場合、それはまた、クロスドメインの問題が発生します、異なる場合があります。そして、ドメイン名の一貫性のない使用はこのような問題になりますがあります。
エラーメッセージ
http://192.168.2.111:8080/loginの読み込みに失敗しました:要求されたリソースには「アクセス制御 - 許可 - 起源」をヘッダispresent。起源「http://192.168.2.110:8084」がゆえのアクセスが許可されていません。応答は、HTTPステータスコード405を持っていました。
とにかく、これはほとんどの上に与えられています。
フロントエンドの実装
あなたはしかし、GETメソッドのみのため、この問題を解決するためのフロントJSONPの方法を使用することができます。
ノードエージェントをサポートすることができます。httpプロキシ・ミドルウェアもオープンソースコンポーネントです。
VaRは発現=(「発現」)を必要とします。
VARプロキシは=(「HTTPプロキシ・ミドルウェア」)が必要です。
VARアプリ=表現();
app.use( '/ API'、プロキシ({対象: 'HTTP://192.168.2.110:8080'、changeOrigin:真}))。
app.listen(3000)。
nginxのは、達成します
逆プロキシの設定
#USERの誰もいません。
1 worker_processes;
#error_logログ/ error.logに。
#error_logログ/ error.logに予告。
#error_logログ/ error.logに情報;
#pidログ/ nginx.pid。
イベント{
worker_connections 1024。
}
HTTP {
のmime.typesを含みます。
default_type application / octet-streamと;
#log_formatメイン'REMOTE_ADDR $ - $のREMOTE_USER [$ time_local] "$依頼"'
# '$ステータスの$ body_bytes_sent "$ HTTP_REFERER"'
# ' "$ HTTP_USER_AGENT" "$ HTTP_X_FORWARDED_FOR"';
#access_logログ/ access.logをメイン;
sendfile;
上#tcp_nopush;
keepalive_timeout 65;
proxy_set_header X-のReal-IP $ REMOTE_ADDR。
上#gzip;
上流AppStoreのウェブ{
サーバー192.168.2.110:8080。
} サーバー{
80聞きます。
SERVER_NAME 192.168.2.111;
1000Mをclient_max_body_size。
#charset KOI8-R。
#access_logログ/ host.access.logメイン。
位置/ {
ルート/ jyzh / AppStoreのフロント/ DIST。
インデックスindex.htmlを。
}
場所/ AppStoreのウェブ{
proxy_passのhttp:// AppStoreのウェブ。
proxy_set_headerホスト$ホスト;
proxy_set_headerのX-転送さ-について$ proxy_add_x_forwarded_for。
}
}
#別のIP-のミックスを使用して仮想ホスト名- 、およびポートベースの構成
#1
の#server {
#8000を聞きます。
#somenameの聞く:8080;
#SERVER_NAME somenameの別名another.alias。
#位置/ {
#ルートHTML。
#インデックスのindex.html index.htmを。
#}
#}
#HTTPSサーバ
#1
の#server {
#443 SSLを聞きます。
#サーバー名はlocalhost。
#ssl_certificateのcert.pem。
#ssl_certificate_keyのcert.key。
#ssl_session_cache共有:SSL:1メートル。
#ssl_session_timeout 5メートル。
#のssl_ciphers HIGH:aNULL:MD5;!
#ssl_prefer_server_ciphers上。
#位置/ {
#ルートHTML。
#インデックスのindex.html index.htmを。
#}
#}
}
バックエンドの実装
フィルタ
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 全局跨域过滤器
*
* @author wzm
* @version 1.0.0
* @date 2020/1/25
**/
public class CrosFilter implements Filter {
public static final Logger LOGGER = LoggerFactory.getLogger(CrosFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) servletResponse;
HttpServletRequest req = (HttpServletRequest)servletRequest;
LOGGER.info("****执行跨域拦截****",req.getRequestURI());
//*号表示对所有请求都允许跨域访问
res.addHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization");
res.addHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
res.setHeader("Access-Control-Max-Age", "3600");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
springboot配置
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* 全局跨域
*
* @author wzm
* @version 1.0.0
* @date 2020/1/25
**/
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "DELETE", "PATCH")
.allowCredentials(true)
.maxAge(3600);
}
}
终极解决办法(CORS)
简单来说,CORS是一种访问机制,英文全称是Cross-Origin Resource Sharing,即我们常说的跨域资源共享,通过在服务器端设置响应头,把发起跨域的原始域名添加到Access-Control-Allow-Origin 即可。
这种方式几乎适用于所有场景。
Request Headers(请求头)
Origin
表示跨域请求的原始域。
Access-Control-Request-Method
表示跨域请求的方式。(如GET/POST)
Access-Control-Request-Headers
表示跨域请求的请求头信息。
Response headers(响应头 )
Access-Control-Allow-Origin
表示允许哪些原始域进行跨域访问。(字符数组)
Access-Control-Allow-Credentials
表示是否允许客户端获取用户凭据。(布尔类型)
从浏览器发起跨域请求,并且要附带Cookie信息给服务器。则必须具备两个条件:
1. 浏览器端:发送AJAX请求前需设置通信对象XHR的withCredentials 属性为true。
2. 服务器端:设置Access-Control-Allow-Credentials为true。两个条件缺一不可,否则即使服务器同意发送Cookie,浏览器也无法获取。
Access-Control-Allow-Methods
表示跨域请求的方式的允许范围。(例如只授权GET/POST)
Access-Control-Allow-Headers
表示跨域请求的头部的允许范围。
Access-Control-Expose-Headers
表示暴露哪些头部信息,并提供给客户端。(因为基于安全考虑,如果没有设置额外的暴露,跨域的通信对象XMLHttpRequest只能获取标准的头部信息)
Access-Control-Max-Age
表示预检请求 [Preflight Request] 的最大缓存时间。
CorsFilter
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 全局跨域
*
* @author wzm
* @version 1.0.0
* @date 2020/1/25
**/
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送Cookie信息
config.setAllowCredentials(true);
//放行哪些原始域(请求方式)
config.addAllowedMethod("*");
//放行哪些原始域(头部信息)
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
config.addExposedHeader("*");
//添加映射路径
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//返回新的CorsFilter
return new CorsFilter(configSource);
}
}
WebMvcConfigurer
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 全局跨域
*
* @author wzm
* @version 1.0.0
* @date 2020/1/25
**/
@Configuration
public class GlobalCorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET","POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Token", "Channel");
}
};
}
}
CrossOrigin注解
1、在方法上(@RequestMapping)使用注解 @CrossOrigin
@RequestMapping("/hello")
@ResponseBody
@CrossOrigin("http://192.168.2.110:8080")
public String hello( ){
return "hello";
}
2、在控制器(@Controller)上使用注解 @CrossOrigin
@Controller
@CrossOrigin(origins = "http://192.168.2.110:8080", maxAge = 3600)
public class HelloController{
@RequestMapping("/hello")
@ResponseBody
public String hello( ){
return "hello";
}
}