Загрузить файл из angular в Spring без настройки CORS - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь осуществить загрузку файлов с помощью Angular.Angular размещается на сервере Apache с этой конфигурацией прокси-модуля:

<Directory /var/www/html/admin>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

<IfModule mod_proxy.c>
    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On
    ProxyStatus On

    ProxyPass           /api_admin http://localhost:8080/api_admin
    ProxyPassReverse    /api_admin http://localhost:8080/api_admin
    ProxyPassReverseCookiePath  /api_admin /
</IfModule>

Я использую эту конфигурацию для размещения приложения Angular в подкаталоге на Apache:

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteBase /admin/
   RewriteCond %{REQUEST_FILENAME} -s [OR]
   RewriteCond %{REQUEST_FILENAME} -l [OR]
   RewriteCond %{REQUEST_FILENAME} !-f [OR]
   RewriteCond %{REQUEST_FILENAME} -d
   RewriteRule ^.*$ - [NC,L]
   RewriteRule ^(.*) index.html [NC,L]
</IfModule>

Код машинописного текста длязагрузка файла:

imports (file: any) {
  const url = `http://111.111.111/api_admin/merchants/upload`;
  const formData = new FormData();
  formData.append('file', file, file.name);
  return this.http.post(url, formData);
}

Конечная точка Spring:

@RestController
@RequestMapping("/merchants")
public class MerchantController {

    @PostMapping("/upload")
        public ResponseEntity<String> uploadData(@RequestParam("file") MultipartFile file) throws Exception {
          .........
    }
}

Конфигурация Spring Security:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DbUserDetailsService dbuserDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return dbuserDetailsService;
    }

    @Override
    protected UserDetailsService userDetailsService() {
        return dbuserDetailsService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(dbuserDetailsService)
                .passwordEncoder(passwordEncoder);
    }

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(dbuserDetailsService)
                .passwordEncoder(passwordEncoder);
    }
}

Пути:

@Configuration
@EnableResourceServer
public class ResourceSecurityConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource_id").stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/users/**").permitAll()
                .anyRequest().authenticated();
    }
}

Но яполучить ошибку CORS.Обычно я могу открыть все страницы и сделать запрос к BE, но только загрузка этого файла не работает.Я попробовал это:

@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS}, allowedHeaders = {"Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"}, exposedHeaders = {"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"})
@PostMapping("/upload")
            public ResponseEntity<String> uploadData(@RequestParam("file") MultipartFile file) throws Exception {
              .........
        }

Но снова запрос на загрузку заблокирован CORS.

Знаете ли вы, как я могу настроить Apache mod_rewrite для правильного перенаправления трафика?

Второй способ, который я попробовал:

@Configuration
@EnableResourceServer
public class ResourceSecurityConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource_id").stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/users/**").permitAll()
                .anyRequest().authenticated()
                .and()
        .cors().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .anyRequest()
        .fullyAuthenticated()
        .and()
        .httpBasic()
        .and()
        .csrf().disable();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSources() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Со второй конфигурацией я получаю has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status. auth:1 Failed to load resource: the server responded with a status of 404 (Not Found)

Каков наилучший способ достижения этого результата?

Есть ли какой-то способреализовать это без отключения CORS?

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Вы отключили совместное использование ресурсов между источниками в вашем ResourceSecurityConfig, настроив .cors().disable().Попробуйте удалить часть disable() и оставить часть .cors().Это включит CORS в части безопасности вашего приложения и вернет ему статус OK в запросе предполетной проверки.

0 голосов
/ 20 января 2019

Несколько комментариев:

  1. Для решения вашей проблемы вы должны использовать response.setStatus(200);
  2. Ваша текущая реализация не использует Spring. Он использует фильтры Java. Spring имеет встроенные инструменты обработки CORS, см. this например
  3. Ваша текущая реализация небезопасна и уязвима для «атак CORS», поскольку вы принимаете все источники. Это позволяет злоумышленнику выполнять действия от имени ваших пользователей и читать их личную информацию. Чтобы предотвратить это, вы должны убедиться, что источник соответствует вашим белым спискам происхождения
...