領域横断的な問題とソリューションの開発におけるフロントエンドとバックエンドの分離
会社の開発モデルはフロントエンドとバックエンドに分かれていないため、実際の開発では、基本的にクロスドメイン要求の問題に遭遇しなかっただけでなく、関連する問題にも注意を払っていませんでした。
問題の記述
フロントエンドとバックエンドの分離の開発では、フロントエンドのページ要求のバックエンドのインターフェイスは、クロスドメインエラーの出現に制御するときがありますが、インターフェイスだけのテストは問題ではありません!
解決方法
フロントエンド処理
- サービスコール時のクロスドメイン処理
- 通常の状況でajaxを使用してサービスを呼び出す場合
$("#demo1").click(function(){
$.ajax({
url : 'http://..top/Index/Test/crossDomain',
data : {},
type : 'get',
success : function (res) {
//No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://...1' is therefore not allowed access. 実行中に報告されたエラーはクロスドメインエラーを表す。
alert(res);
}
});
});
- インターフェイスの呼び出しにjsonpを使用しますが、この方法はGETリクエストに限られており、制約が多すぎます。
$("#demo2").click(function(){
$.ajax({
url : 'http://..top/Index/Test/crossDomain',
data : {},
type : 'get',
dataType : 'jsonp',
success : function (res) {
alert(res);
}
});
});
- リバースプロキシによるクロスドメイン問題の処理
vue-cliプロジェクトの場合、プロジェクトのルートディレクトリにグローバル設定ファイルvue.config.jsを作成します。
module.exports = {
// 基本パス
publicPath:"./", // を相対パスに設定することで、すべてのリソースが相対パスにリンクされ、パッケージを任意のパスにデプロイすることができる。
outputDir:"dist", //パッケージング時に生成される本番環境ビルドファイルのディレクトリ
assetsDir: 'public', // 生成された静的リソースを置くディレクトリ
devServer: {
//プロキシモード。インターフェイスのクロスドメイン問題を解決するために使われる
proxy: {
'/api': {
//target: '"http://localhost:8100"/pm', // 自身のインターフェースに対応する
target : '"http://...189:8100"/pm',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': '',
},
},
},
}
}
バックエンド処理
- プロジェクトが SpringBoot の場合は、Controller クラスの jdk バージョン 1.8 以降に @CrossOrigin アノテーションを直接追加します。
/**
クロスドメイン問題を解決するために、他のコントロールレイヤーはこのクラスを継承することができる。
*/
@CrossOrigin
public class commonController {
}
- インターセプター・アプローチによる実装
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private EnvConfig envConfig;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
boolean isTrue = envConfig.getIsDev();//クロスドメインの問題を解決するだけのテストサービスであると判断する
if (isTrue) {
response.addHeader("Access-Control-Allow-Origin", "*");
           response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers",
"Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
}
});
}
}
- フィルターによる判断
@Configuration
public class GlobalCorsConfig {
/**
* フィルタへのクロスドメイン呼び出しを許可する
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//すべてのドメインにクロスドメイン呼び出しを許可する
config.addAllowedOrigin("*");
//クッキーの送信を許可する
config.setAllowCredentials(true);
//すべての生ヘッダを解放する
config.addAllowedHeader("*");
//すべてのリクエストメソッドをドメインをまたいで呼び出せるようにする
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
- グローバルコンフィギュレーション用のグローバルコンフィギュレーター。
@Configuration
public class CorsMappingConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/dev/**")
.allowCredentials(true)
.allowedMethods("GET","PUT","DELETE","POST","OPTIONS")
.maxAge(3600);
}
}
Nginx介入方法
設定ファイルは次のとおりです。
server{
listen 8888;
server_name 192.0;
# の静的ページ
location /{
proxy_pass "http://...100:8080";
}
# api
location /api{
proxy_pass "http://localhost:8100"/api;
}
}