【问题标题】:Angular 4 + Java EE + Basic Auth + JAX-RS + Chrome throwing CORS issueAngular 4 + Java EE + Basic Auth + JAX-RS + Chrome 抛出 CORS 问题
【发布时间】:2018-02-01 08:33:45
【问题描述】:

我正在使用 Angular 4 和 JAX-RS 来提供休息服务。 Angular 部署在 tomcat 服务器中,JAX-RS REST 服务部署在 Websphere 8.5 App 服务器中。我正在尝试使用基本身份验证来保护其余服务。这是用于解决 CORS 问题和基本身份验证的 web.xml 部分

<filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowSubdomains</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, PUT, DELETE, OPTIONS, HEAD </param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>-1</param-value>
        </init-param>
    </filter>
    <filter-mapping>
            <filter-name>CORS</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping> 

<security-role>
        <description>default</description>
        <role-name>default</role-name>
    </security-role>

     <security-constraint>
        <display-name>DefaultConstraints</display-name>
        <web-resource-collection>
            <web-resource-name>all resources</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
            <http-method>PUT</http-method>
            <http-method>HEAD</http-method>
            <http-method>TRACE</http-method>
            <http-method>DELETE</http-method>
            <http-method>OPTIONS</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>default</role-name>
        </auth-constraint>
    </security-constraint>  

     <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>

当 Angular 应用程序在 Java web 中使用上述配置从 chrome 浏览器调用 Rest 服务时,它会抛出错误,并在浏览器控制台中看到以下内容。

加载资源失败:服务器响应状态为 401(未授权)

无法加载http://localhost:9091/xxxxxxx/rest/v1/technologies:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost:8080' 不允许访问。响应的 HTTP 状态代码为 401。

如果同一个 Angular 应用程序从 IE 调用其余服务,浏览器会弹出一个凭据弹出窗口,并且在成功登录后,Angular 能够获取并显示记录。

它适用于 IE,不适用于 chrome。

如果我删除安全约束、基本身份验证、角色并仅放置 CORS 过滤器,Angular 就能够从 chrome 和 IE 中的其余服务中获取记录。如果在安全约束时仅在 chrome 中失败。

请帮我解决。如果有任何错误,请告诉我。

谢谢, 哈里。

【问题讨论】:

    标签: angular jakarta-ee jax-rs basic-authentication


    【解决方案1】:

    这是因为您的服务器 (API) 部署在 localhost:9091 上,而您的前端应用程序 (Angular APP) 位于 localhost:8080 上。

    要进行 api 调用,或者说 http 调用,Angular 中有 Http/HttpClient 模块,然后在本机浏览器级别实现,这里的问题是,浏览器检测到来自应用程序的请求 (:8080)正在调用另一个资源 (:9091) 可能是一个 CORS 请求。

    来自Wikipedia的定义

    跨域资源共享。跨域资源共享 (CORS) 是一种机制,允许从提供第一个资源的域之外的另一个域请求网页上的受限资源(例如字体)。

    为了确保上述机制正常工作,浏览器通过在每个请求之前进行额外调用来阻止调用。这些请求是 OPTIONS 类型的请求,如果服务器响应“yes.. CORS allowed.”。然后浏览器将使您的呼叫继续进行,否则它将引发错误(正是您所得到的)。

    解决方案,

    在部署 Angular 应用时使用代理。

    ng serve --aot --port 3300 --proxy-config proxy-conf.json

    在这里,我在端口:3300 上部署我的 Angular 应用程序,并说,使用存储在 proxy-conf.json 文件中的代理配置。

    在哪里,proxy-conf.json 文件有..

        [
            {
                "context": [
                    "/api",
                    "/auth"
                ],
                "target": "http://localhost:8001",
                "secure": false
            }
        ]
    

    在上述配置的context 数组中,我说cli,仅对带有/api,/auth 的请求的请求应用代理。这是您需要根据您的 API 端点自定义的内容。

    target 键用于指出您的 API 的位置。 (我在端口:8001 上部署了我的 API)

    希望对你有帮助。!!

    【讨论】:

    • 嗨 Manoj,如果我使用 ng serve 之类的 angular cli 运行 angular 应用程序,上述解决方案适用于我……但是如果我使用 ng build 并将 dist 文件夹部署到网络服务器,它不工作。请建议
    • 你还能做的是,使用ng build --base-href http://localhost:9091/,并在你的角度应用程序中创建一个httpInterceptor(我假设你已经拥有它),然后在那里创建一个简单的变量,baseUrl = /xxxxxxx/rest/v1/technologies/然后,对于每个 http 调用,例如 http.get(urlOfGet) 将其替换为 http.get(baseUrl+urlOfGet),这肯定可以工作,因为所有调用都将被监听 localhost:9091 作为托管 url,因此没有交叉问题,拦截器中的 baseUrl 会区分仅用于 api 调用的路径。让我知道它是否有效,这是一个有趣的问题。 :P
    • 嗨 Manoj,我对解决方案有疑问,因为我将在 web 服务器中部署 angular 应用程序,如 tomcat 并且它在 localhost:8080 上运行,我必须首先访问应用程序,如 localhost:8080/区当我点击它时,它会请求 localhost:9091 并导致同样的问题
    • localhost:9091/xxxxxxx/rest/v1/technologies 401(未经授权):8080/dist/login:1 无法加载localhost:9091/xxxxxxxx/rest/v1/technologies:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'localhost:8080' 不允许访问。响应的 HTTP 状态代码为 401。
    • 你的 REST API 是否在 9091 上运行?如果是,则将应用程序部署到同一端口。
    【解决方案2】:

    尝试安装 CORS 扩展:

    https://chrome.google.com/webstore/detail/cors-toggle/jioikioepegflmdnbocfhgmpmopmjkim?hl=en

    在我的情况下工作正常。

    【讨论】:

    【解决方案3】:

    您从浏览器收到此错误。您收到错误是因为您的应用程序不在同一个域中。我建议使用代理。在CLI 中有一个选项。这样,它将是一次性配置。

    另一种选择是在浏览器中安装 CORS 插件。然而,这将要求每个开发人员在他们使用的每个浏览器上安装它。

    【讨论】:

    • 是的。 Angular 代理它工作。但这仅在开发过程中和 Angular 运行 Angular CLI/服务器时才有帮助。但是当它部署在像tomcat这样的网络服务器中时,我认为它不起作用。请提出建议。
    • 在将您的应用部署到 tomcat 容器之前,您的应用必须通过应用代理配置来构建,一旦使用它编译/构建,您就可以部署到任何容器,它可以工作。
    【解决方案4】:

    在 Chrome/Firefox 中,没有为 XMLHttprequest 设置 WAS LTPA2 令牌 cookie。添加 withCredentials:true 后,http 获取请求也在 chrome/firefox 中工作。在选项中添加后,Chrome 现在正在添加 cookie。

    return this.http.post(environment.frameworkUrl,framework,
      {withCredentials: true} );
    }
    

    但同样不适用于发布请求。 Chrome 不会为发布请求添加 cookie。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 2017-07-18
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-15
      相关资源
      最近更新 更多