Spring Security
を既存のプロジェクトに追加しました。
この瞬間から、サーバーから401 No 'Access-Control-Allow-Origin' header is present on the requested resource
エラーを受け取ります。
これは、Access-Control-Allow-Origin
ヘッダーが応答に添付されていないためです。これを修正するために、ログアウトフィルターの前にFilter
チェーンにある独自のフィルターを追加しましたが、フィルターはリクエストには適用されません。
エラー:
XMLHttpRequestは
http://localhost:8080/getKunden
をロードできません。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、Originhttp://localhost:3000
はアクセスを許可されていません。応答のHTTPステータスコード401。
セキュリティ構成:
@EnableWebSecurity
@Configuration
@ComponentScan("com.company.praktikant")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilter filter;
@Override
public void configure(HttpSecurity http) throws Exception {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
source.registerCorsConfiguration("/**", config);
http.addFilterBefore(new MyFilter(), LogoutFilter.class).authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/*").permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
}
}
私たちのフィルター
@Component
public class MyFilter extends OncePerRequestFilter {
@Override
public void destroy() {
}
private String getAllowedDomainsRegex() {
return "individual / customized Regex";
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String Origin = "http://localhost:3000";
response.addHeader("Access-Control-Allow-Origin", Origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers",
"content-type, x-gwt-module-base, x-gwt-permutation, clientid, longpush");
filterChain.doFilter(request, response);
}
}
私たちのアプリケーション
@SpringBootApplication
public class Application {
public static void main(String[] args) {
final ApplicationContext ctx = SpringApplication.run(Application.class, args);
final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(CORSConfig.class);
annotationConfigApplicationContext.refresh();
}
}
フィルターはspring-bootから登録されます:
2016-11-04 09:19:51.494 INFO 9704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean:マッピングフィルター: 'myFilter'から:[/ *]
生成されたフィルターチェーン:
2016-11-04 09:19:52.729 INFO 9704 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain:フィルターチェーンの作成:org.springframework.security.web.util.matcher.AnyRequestMatcher@1、[org。 springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter @ 5d8c5a8a、org.springframework.security.web.context.SecurityContextPersistenceFilter @ 7d6938f、org.springframework.security.web.header.HeaderWriterFilter @ 72aa89c、org.springframework.security。 web.csrf.CsrfFilter @ 4af4df11、com.company.praktikant.MyFilter @ 5ba65db2、org.springframework.security.web.authentication.logout.LogoutFilter @ 2330834f、org.springframework.security.web.savedrequest.RequestCacheAwareFilter @ 396532d1、org。 springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4fc0f1a2、org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2357120f、org.springframework.security.web.session.SessionManagementFilter@10867bfb、org.springframework.security.web.access。例外TranslationFilter @ 4b8bf1fb、org.springframework.security.web.access.intercept.FilterSecurityInterceptor @ 42063cf1]
応答: 応答ヘッダー
春からの解決策も試しましたが、うまくいきませんでした!コントローラーのアノテーション@CrossOriginも役に立たなかった。
@PiotrSołtysiakからソリューションを試しました。 corsフィルターは、生成されたフィルターチェーンにリストされておらず、同じエラーが発生します。
2016-11-04 10:22:49.881 INFO 8820 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain:フィルターチェーンの作成:org.springframework.security.web.util.matcher.AnyRequestMatcher@1、[org。 springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter @ 4c191377、org.springframework.security.web.context.SecurityContextPersistenceFilter @ 28bad32a、org.springframework.security.web.header.HeaderWriterFilter @ 3c3ec668、org.springframework.security。 web.csrf.CsrfFilter @ 288460dd、org.springframework.security.web.authentication.logout.LogoutFilter @ 1c9cd096、org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter @ 3990c331、org.springframework.security.web.authentication.ui。 DefaultLoginPageGeneratingFilter @ 1e8d4ac1、org.springframework.security.web.authentication.www.BasicAuthenticationFilter@2d61d2a4、org.springframework.security.web.savedrequest.RequestCacheAwareFilter@380d9a9b、org.springframework.security.web.servletapi.SecurityContextHolderAwar eRequestFilter @ abf2de3、org.springframework.security.web.authentication.AnonymousAuthenticationFilter @ 2a5c161b、org.springframework.security.web.session.SessionManagementFilter @ 3c1fd3e5、org.springframework.security.web.access.ExceptionTranslationFilter @ 3d7055ef、org.springframework。 security.web.access.intercept.FilterSecurityInterceptor@5d27725a]
ところで、私たちはspring-securityバージョン4.1.3を使用しています。
OK、2日間以上の検索の後、最終的に問題を修正しました。すべてのフィルターと構成を削除し、代わりにアプリケーションクラスでこの5行のコードを使用しました。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
final ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:3000");
}
};
}
}
Spring Security 4.1以降、これはSpring SecurityがCORSをサポートするための適切な方法です(Spring Boot 1.4/1.5でも必要です)。
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
そして:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().disable();
http.cors();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
notは以下のいずれかを実行しますが、これは問題の解決を試みるための間違った方法です
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
リファレンス: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
私は他のソリューションに問題があったので(特にすべてのブラウザで動作させるため、たとえばEdgeは「Access-Control-Allow-Methods」の有効な値として「*」を認識しません)、カスタムを使用する必要がありました最終的に私のために働いて、私が達成したかったものを正確にやったフィルターコンポーネント。
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods",
"ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
public void init(FilterConfig filterConfig) {
// not needed
}
public void destroy() {
//not needed
}
}
必要ありません:
@Configuration
@ComponentScan("com.company.praktikant")
@EnableWebSecurity
にはすでに@Configuration
が含まれていますが、なぜ@ComponentScan
を配置したのか想像できません。
CORSフィルターについては、次のようにします。
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
SecurityConfigurationクラスに移動し、構成を削除し、グローバルメソッドを構成します。許可元、ヘッダー、メソッドを2回設定する必要はありません。特に、フィルターとスプリングセキュリティ構成に異なるプロパティを配置する場合:)
上記によれば、「MyFilter」クラスは冗長です。
これらを削除することもできます:
final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(CORSConfig.class);
annotationConfigApplicationContext.refresh();
アプリケーションクラスから。
最後に小さなアドバイス-質問に接続されていません。 URIに動詞を入れたくありません。 http://localhost:8080/getKunden
の代わりに、http://localhost:8080/kunden
リソースでHTTP GETメソッドを使用する必要があります。 RESTful APIの設計のベストプラクティスについては、こちらでご覧いただけます。 http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Spring Boot 2のSpring Securityを使用してCORSをグローバルに構成する(たとえば、開発のすべての要求を有効にする)と、次のことができます。
@Bean
protected CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and().authorizeRequests()
.anyRequest().permitAll()
.and().csrf().disable();
}
「Spring MVCは、コントローラーの注釈を通じてCORS設定のきめ細かなサポートを提供します。ただし、Spring Securityで使用する場合は、事前に注文する必要がある組み込みのCorsFilterに依存することをお勧めしますSpring Securityの一連のフィルター」
このようなものは、GET
への/ajaxUri
へのアクセスを許可します:
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import Java.util.Arrays;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AjaxCorsFilter extends CorsFilter {
public AjaxCorsFilter() {
super(configurationSource());
}
private static UrlBasedCorsConfigurationSource configurationSource() {
CorsConfiguration config = new CorsConfiguration();
// origins
config.addAllowedOrigin("*");
// when using ajax: withCredentials: true, we require exact Origin match
config.setAllowCredentials(true);
// headers
config.addAllowedHeader("x-requested-with");
// methods
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.GET);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/startAsyncAuthorize", config);
source.registerCorsConfiguration("/ajaxUri", config);
return source;
}
}
もちろん、SpringSecurity構成では、リストされたメソッドを使用してURIへのアクセスを許可する必要があります。 @Hendy Irawanの回答をご覧ください。
多くの場所で、このコードを追加する必要がある答えがあります。
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
しかし、私の場合、予期しないクラスタイプの例外がスローされます。 corsFilter()
BeanにはCorsFilter
タイプが必要であるため、この変更を行って、このBeanの定義を構成に追加しました。これで問題ありません。
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
私の場合、このクラスを追加して@EnableAutConfigurationを使用しました
package com.package.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import Java.io.IOException;
@Component
public class SimpleCORSFilter extends GenericFilterBean {
/**
* The Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
logger.info("> doFilter");
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
//response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(req, resp);
logger.info("< doFilter");
}
}
既に展開されており、コードの変更に余裕がないプログラム(たとえば、スプリングセキュリティの追加/更新)の場合、単純なプロキシを追加することが1つのソリューションです。 https://stackoverflow.com/a/49827300/1758194