【问题标题】:Access to azure hosted API App denied by CORS policyCORS 策略拒绝访问 Azure 托管 API 应用程序
【发布时间】:2016-11-22 19:18:25
【问题描述】:

我们是一个致力于 azure Web 服务的团队。我们想要实现的是拥有一个 JavaScript 前端,它可以与托管在 Azure 中的 Java API 应用程序进行通信。

我们正在使用 Active Directory 进行身份验证。我们已经在 Azure 门户中配置了 CORS。

我们已经使用 Swagger Editor 创建了一个 Java 后端,如 this article 中所述。我们刚刚推进了这个例子来支持我们自己的数据模型。所以ApiOriginFilter 类也没有改变:

@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-11-08T15:40:34.550Z")
public class ApiOriginFilter implements javax.servlet.Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type");
        chain.doFilter(request, response);

    }

    public void destroy() {}

    public void init(FilterConfig filterConfig) throws ServletException {}
}

我们的前端在本地 PC 上运行。此外,我们在 azure 门户的 CORS 中添加了我们的来源“http://localhost:8888”。

前端 JavaScript 代码如下所示:

var app = angular.module('demo', ['AdalAngular', 'ngRoute'])
    .controller('GetDataController', ['$scope', '$http', '$timeout', 'adalAuthenticationService', function($scope, $http, $timeout, adalAuthenticationService) {
        $scope.loggedIn = "Logged out";
        $scope.responseData = "No Data";
        $scope.loading = "";

        $scope.loginAdal = function(){
          adalAuthenticationService.login();
        }

        $scope.getData = function(){            
          $http.defaults.useXDomain = true;
          delete $http.defaults.headers.common['X-Requested-With'];

          $scope.loading = "loading...";
          var erg = $http.get('http://<our-backend>.azurewebsites.net/api/contacts')
            .success(function (data, status, headers, config) {
                console.log("SUCCESS");
                $scope.loading = "Succeeded";
                $scope.loggedIn = "LOGGED IN";
                $scope.responseData = data;     
            })
            .error(function (data, status, header, config) {
                console.log("ERROR");
                $scope.loading = "Error";
                console.log("data: ", data);
            });
        }
    }]);

    app.config(['$locationProvider', 'adalAuthenticationServiceProvider', '$httpProvider', '$routeProvider', function($locationProvider, adalAuthenticationServiceProvider, $httpProvider, $routeProvider) {

        $locationProvider.html5Mode({
          enabled: true,
          requireBase: false,
          hashPrefix: '!'
        });

        var theEndpoints = {
          "https://<our-backend>.azurewebsites.net/api/contacts": "f0f91e4a-ad53-4a4a-ac91-431dd152f386", 
        };

        adalAuthenticationServiceProvider.init(
        {
            anonymousEndpoints: [],
            instance: 'https://login.microsoftonline.com/',
            tenant: "<our-tenant>.onmicrosoft.com", 
            clientId: "f6a7ea99-f13b-4673-90b8-ef0c5de9822f", 
            endpoints: theEndpoints 
        },
        $httpProvider 
        );
}]);

但是从前端调用后端我们在登录到我们的租户后得到以下错误:

XMLHttpRequest 无法加载 https://[our-backend].azurewebsites.net/api/contacts。从“https://[our-backend].azurewebsites.net/api/contacts”重定向到 'https://login.windows.net/12141bed-36f0-4fc6-b70c- 43483f616eb7/oauth2/授权... %2Fapi%2Fcontacts%23&nonce=7658b7c8155b4b278f2f1447d4b77e47_20161115124144' 已被 CORS 策略阻止:没有“访问控制允许来源” 请求的资源上存在标头。原点“空”是 因此不允许访问。

在 Chrome 的开发者控制台中,我们看到了对联系人 API 的四个请求。但都有状态码“302 Redirect”。前两个条目包含标题“Access-Control-Allow-Origin:http://localhost:8888”,但其他两个条目包含此标题。

编辑:前两个条目之一是 XmlHttpRequest,第二个条目之一是相同的 XmlHttpRequest,但使用 https 而不是 http

基于此,我们在后端创建了一个新的过滤器来设置 access-control-allow-origin 字段:

@Provider
public class CrossOriginFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
        containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
        containerResponseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        containerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
        containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
        containerResponseContext.getHeaders().add("Access-Control-Max-Age", "1209600");    
    }
}

并从 ApiOriginFilter 中删除这三个字段:

res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");

现在,如果我们在本地运行 后端,我们会在 Chrome 的开发者控制台中看到来自第二个过滤器的所有这些标头。

但是,一旦我们将后端部署到 azure,我们就会以某种方式丢失此标头,并且在从前端访问 api 时会再次出现相同的错误:

XMLHttpRequest 无法加载 https://[our-backend].azurewebsites.net/api/contacts。从“https://[our-backend].azurewebsites.net/api/contacts”重定向到 'https://login.windows.net/12141bed-36f0-4fc6-b70c- 43483f616eb7/oauth2/授权... %2Fapi%2Fcontacts%23&nonce=7658b7c8155b4b278f2f1447d4b77e47_20161115124144' 已被 CORS 策略阻止:没有“访问控制允许来源” 请求的资源上存在标头。原点“空”是 因此不允许访问。

编辑:正如我所写,有两个 XmlHttpRequests。第二个是https。所以如果在行

var erg = $http.get('http://<our.backend>.azurewebsites.net/api/contacts')

我将 http 更改为 https 我们遇到了error() 回调函数。在控制台中我们有输出:

数据:需要用户登录

但正如我之前写的那样。我们已经登录到我们的租户。那么到底出了什么问题呢?

【问题讨论】:

    标签: java azure active-directory cors azure-active-directory


    【解决方案1】:

    var erg = $http.get('http://.azurewebsites.net/api/contacts')

    根据代码,您使用 HTTP 协议请求服务。当我使用 HTTP 请求受 Azure AD 保护的 Web API 时,我能够重现此问题。 Azure AD 似乎会将 HTTP 重定向到 HTTPS

    使用 HTTPS 更改服务 URL 后,问题已解决。请让我知道它是否有帮助。

    【讨论】:

    • 谢谢。但正如我所写:“我们正在使用 Active Directory 进行身份验证。我们已经在 Azure 门户中配置了 CORS。”因此,我们已经进行了您所要求的设置,但仍然遇到上述问题。
    • 我已经更新了帖子,请查看是否有帮助。
    • 不,抱歉。没有帮助。我们也在尝试 https。请注意我们的最新帖子:stackoverflow.com/questions/40630172/…
    • 根据错误信息,请求没有被授权,被重定向到不支持跨域的授权端点。请检查令牌是否正确或过期。当我发送带有过期令牌的请求时,我也可以重现此问题。您可以通过在门户上启用允许匿名请求(无操作)来验证此问题。
    猜你喜欢
    • 2014-08-06
    • 1970-01-01
    • 2022-08-22
    • 2021-10-15
    • 2021-12-09
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多