【问题标题】:Response for preflight has invalid HTTP status code 403预检响应具有无效的 HTTP 状态代码 403
【发布时间】:2016-04-14 04:23:36
【问题描述】:

我正在使用服务器端 Spring-boot 并提供一个虚拟服务进行测试

我的 ServiceCaller.java=

package com.user.server.mfw;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.handler.MappedInterceptor;


@RestController
public class ServiceCaller {
    @CrossOrigin(allowedHeaders="*",allowCredentials="true")
    @RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
    @ResponseBody
    String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException 
    {


        if(!serviceName.isEmpty())
        {
           byte[] encoded = Files.readAllBytes(Paths.get("C://Users//something//Desktop//asd.json"));
           return new String(encoded, "UTF-8");
        }
        return "gelemedi";
    }


    private void checkActiveSessionControl(HttpSession session)
    {   
        System.out.println("Session Id:" +  session.getId() +" // " + session.getCreationTime());
        if(session == null)
            System.out.println("Null");
        else if(session.isNew())
            System.out.println("New");
        else
            System.out.println("Old");
    }



}

我的客户端是一个离子框架并基于 angular.js...

Controller.js

   $scope.getInfo = function() {
    $http({
        url: SERVER_ENDPOINT.url + '/serviceCaller',
        method: 'POST',
        params: {serviceName: 'deneme'},
        withCredentials: true
    }).then(function(result) {
      var alertPopup = $ionicPopup.alert({
        title: 'ALOHA!',
        template: 'dksjd ' + result
      });
      $scope.memberInfo = result.data.accountNumber;
    }, function() {
        var alertPopup = $ionicPopup.alert({
          title: ' failed!',
          template: 'da'
        });
      }

    );
  };

当我使用 POST 方法而不是 GET 时,基本上我会收到“无效的 HTTP 状态代码 403”。不过,我想使用 POST 来代替 GET 进行调用。 但是我无法弄清楚我在哪里犯了错误......

任何解决方案将不胜感激!

【问题讨论】:

    标签: angularjs http spring-boot ionic-framework


    【解决方案1】:

    如果您的浏览器正在发送飞行前 OPTIONS 请求,您所要做的就是通过允许 http OPTIONS 在您的 WebSecurity 配置中允许它。

    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    

    【讨论】:

    • 男士们,非常感谢 30 种解决方案,这对我有用,哈哈
    【解决方案2】:

    我认为您没有使用此注释传递任何参数:

    @CrossOrigin(allowedHeaders="*",allowCredentials="true")
    @RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
    @ResponseBody
    String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException 
    {
    

    你应该用value="/{serviceCaller}"替换value="/serviceCaller"

    编辑

    请将该类添加到您的项目中以解决 CORS 问题

    @Component
    public class SimpleCORSFilter implements Filter {
    
    @Override
    public void init(FilterConfig fc) throws ServletException {}
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        HttpServletResponse response = (HttpServletResponse) resp;
    
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, resp);
    }
    
    @Override
    public void destroy() {}
    
    }
    

    【讨论】:

    • l 实际上在此服务之前我创建了登录名并在那里我调用“GET”并且一切正常并且在那里我定义为 RequestMapping(value="/loginService", method=RequestMethod.GET) 虽然我尝试了您的解决方案...不,它没有用
    • 请尝试更改此设置:@RequestParam(value = "serviceName")
    • 同样的错误...请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'localhost:8100' 不允许访问。响应的 HTTP 状态代码为 403。
    • 请将@CrossOrigin(allowedHeaders="*",allowCredentials="true") 替换为下面的 y 类帖子
    • 我很抱歉,但没有解决它
    【解决方案3】:

    AngularJS docs所示

    XSRF 是一种技术,未经授权的网站可以通过该技术获取您用户的私人数据。 Angular 提供了一种机制来对抗 XSRF。在执行 XHR 请求时,$http 服务从 cookie 中读取一个令牌(默认为 XSRF-TOKEN)并将其设置为 HTTP 标头(X-XSRF-TOKEN)。由于只有在您的域上运行的 JavaScript 才能读取 cookie,因此您的服务器可以确信 XHR 来自在您的域上运行的 JavaScript。跨域请求不会设置header。

    所以默认标头是 x-xsrf-token。

    在 CsrfFilter 之后的 websecurityconfiguration 中添加这个过滤器

    public class CsrfHeaderFilter extends OncePerRequestFilter {
      @Override
      protected void doFilterInternal(HttpServletRequest request,
          HttpServletResponse response, FilterChain filterChain)
          throws ServletException, IOException {
    
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        if (csrf != null) {
          Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
          String token = csrf.getToken();
          if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
            cookie = new Cookie("XSRF-TOKEN", token);
            cookie.setPath("/");
            response.addCookie(cookie);
          }
        }
        filterChain.doFilter(request, response);
      }
    }
    

    添加过滤器,如下所示:

    protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        http
          .httpBasic()...
          .and()
          .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
      }
    }
    

    【讨论】:

      【解决方案4】:

      我发现在回答问题Angularjs Post not sending headers to Spring JWT时对预检请求的解释非常清楚。

      由于您使用的是 Spring Security,因此您还必须在 Spring Security 级别启用 CORS,以允许它利用 Spring MVC 级别定义的配置:

      @EnableWebSecurity
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.cors().and()...
          }
      }
      

      Here 是非常优秀的教程,解释了 Spring MVC 框架中的 CORS 支持。

      这使HttpMethod.Options 请求能够在预检请求中包含标头。

      【讨论】:

        猜你喜欢
        • 2016-02-08
        • 2018-04-05
        • 2018-09-22
        • 2018-09-30
        • 1970-01-01
        • 2018-01-25
        • 2016-12-26
        • 2018-04-11
        • 2016-01-18
        相关资源
        最近更新 更多