58
задан 24 April 2018 в 07:24

2 ответа

По некоторым причинам эта простая проблема блокирует многих разработчиков. Я боролся в течение многих часов с этой простой вещью. Эта проблема как много размеров:

  1. CORS (если Вы используете frontend и бэкенд на различных доменах и портах.
  2. Бэкенд Конфигурация CORS
  3. конфигурация Стандартной аутентификации Axios

CORS

Моя установка для разработки является с vuejs webpack приложением, работающим localhost:8081 и пружинным приложением начальной загрузки, работающим localhost:8080. Таким образом, при попытке назвать отдых API от frontend, нет никакого способа, которым браузер позволит мне получить ответ от пружинного бэкенда без надлежащих настроек CORS. CORS может использоваться для ослабления Перекрестного Доменного Сценария (XSS) защита, которую имеют современные браузеры. Поскольку я понимаю это, браузеры защищают Ваш SPA от того, чтобы быть нападением XSS. Конечно, некоторые ответы на StackOverflow предложили добавить хромовый плагин для отключения защиты XSS, но это действительно работает И если бы это было, то только на потом продвинул бы неизбежную проблему.

Бэкенд конфигурация CORS

Вот - то, как необходимо установить CORS в пружинном приложении начальной загрузки:

Добавляют класс CorsFilter для добавления надлежащих заголовков в ответ на клиентский запрос. Access-Control-Allow-Origin и Access-Control-Allow-Headers являются самой важной вещью иметь для стандартной аутентификации.

    public class CorsFilter implements Filter {

...
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        **response.setHeader("Access-Control-Allow-Headers", "authorization, Content-Type");**
        response.setHeader("Access-Control-Max-Age", "3600");

        filterChain.doFilter(servletRequest, servletResponse);

    }
...
}

Добавляют класс конфигурации, который расширяет Spring WebSecurityConfigurationAdapter. В этом классе Вы введете свой фильтр CORS:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
    @Bean
    CorsFilter corsFilter() {
        CorsFilter filter = new CorsFilter();
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
          .csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/api/login")
          .permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic()
          .authenticationEntryPoint(authenticationEntryPoint)
          .and()
          .authenticationProvider(getProvider());
    }
...
}

Вы не должны помещать ничего связанного с CORS в Вашем контроллере.

Frontend

Теперь, в frontend необходимо создать запрос axios с заголовком Авторизации:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
    <p>{{ status }}</p>
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            status: ''
        },
        created: function () {
            this.getBackendResource();
        },
        methods: {
            getBackendResource: function () {
                this.status = 'Loading...';
                var vm = this;
                var user = "aUserName";
                var pass = "aPassword";
                var url = 'http://localhost:8080/api/resource';

                var authorizationBasic = window.btoa(user + ':' + pass);
                var config = {
                    "headers": {
                        "Authorization": "Basic " + authorizationBasic
                    }
                };
                axios.get(url, config)
                    .then(function (response) {
                        vm.status = response.data[0];
                    })
                    .catch(function (error) {
                        vm.status = 'An error occured.' + error;
                    })
            }
        }
    })
</script>
</body>
</html>

Hope это помогает.

3
ответ дан 1 November 2019 в 13:56

Решение, данное luschn и pillravi, хорошо работает, если Вы не получаете Строгая Транспортная безопасность заголовок в ответе.

Добавление withCredentials: верный решит ту проблему.

  axios.post(session_url, {
    withCredentials: true,
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/json"
    }
  },{
    auth: {
      username: "USERNAME",
      password: "PASSWORD"
  }}).then(function(response) {
    console.log('Authenticated');
  }).catch(function(error) {
    console.log('Error on Authentication');
  });
1
ответ дан 1 November 2019 в 13:56

Другие вопросы по тегам:

Похожие вопросы: