java - CORS 策略拒绝访问 azure 托管的 API 应用程序

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

我们是一个致力于 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 cannot load https://[our-backend].azurewebsites.net/api/contacts. Redirect from 'https://[our-backend].azurewebsites.net/api/contacts' to 'https://login.windows.net/12141bed-36f0-4fc6-b70c- 43483f616eb7/oauth2/autho… %2Fapi%2Fcontacts%23&nonce=7658b7c8155b4b278f2f1447d4b77e47_20161115124144' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

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

编辑:前两个条目之一是 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 开发者控制台的第二个过滤器中看到所有这些 header 。

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

XMLHttpRequest cannot load https://[our-backend].azurewebsites.net/api/contacts. Redirect from 'https://[our-backend].azurewebsites.net/api/contacts' to 'https://login.windows.net/12141bed-36f0-4fc6-b70c- 43483f616eb7/oauth2/autho… %2Fapi%2Fcontacts%23&nonce=7658b7c8155b4b278f2f1447d4b77e47_20161115124144' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

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

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

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

data: User login is required

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

最佳答案

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

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

在我将服务 URL 更改为 HTTPS 后,问题得到解决。请告诉我是否有帮助。

关于java - CORS 策略拒绝访问 azure 托管的 API 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40610111/

相关文章:

asp.net-mvc - 第一次成功登录后第二次登录导致无限重定向循环 MVC .NET 5 OWIN ADAL OpenIDConnect

powershell - Powershell:在AD中检查重复的电子邮件

c# - 从 AD 获取扩展属性?

C#:更改事件目录用户密码时出现代码错误

java - android java 膨胀异常

java - 我如何更改方法传递的值?

azure - 使用本地镜像进行 Read 3.0、Azure 认知服务、计算机视觉

sql - 如何隔离不同客户的SQL数据?

Java执行命令行程序 'find'返回错误

java - Hibernate Validator @SafeHtml 不允许自定义 HTML 标签和属性