具有基本身份验证XMLHttpRequest的Tomcat7 REST服务

时间:2013-12-05 13:58:05

标签: rest tomcat basic-authentication

我只是在设置一个小型的TestScenario。我正在使用Jersey在Tomcat 7上公开REST服务。该服务由另一个Javascript / HTML5应用程序通过XMLHttpRequest调用。 为了测试,我只使用Tomcat在我的eclipse安装中运行REST服务。

从JavaScript调用REST服务可以正常工作而无需任何身份验证设置。

现在我正在尝试将基本身份验证机制添加到我的REST服务中。在我的web项目的web.xml中,我添加了

 <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>ImageLinksServices</display-name>
      <servlet>
            <servlet-name>Jersey REST Service</servlet-name>
            <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>com.sun.jersey.config.property.packages</param-name>
                <param-value>com.xxx.xxx.services</param-value>
            </init-param>
            <init-param>
                <param-name>readonly</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Jersey REST Service</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>



        <filter>
            <filter-name>CorsFilter</filter-name>
            <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
            <init-param>
                <param-name>cors.allowed.origins</param-name>
                <param-value>*</param-value>
            </init-param>
            <init-param>
                <param-name>cors.allowed.methods</param-name>
                <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
            </init-param>
            <init-param>
                <param-name>cors.allowed.headers</param-name>
                <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
            </init-param>
            <init-param>
                <param-name>cors.exposed.headers</param-name>
                <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
            </init-param>
            <init-param>
                <param-name>cors.support.credentials</param-name>
                <param-value>true</param-value>
            </init-param>
            <init-param>
                <param-name>cors.preflight.maxage</param-name>
                <param-value>10</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CorsFilter</filter-name>
            <url-pattern>/*</url-pattern>

        </filter-mapping>

        <security-constraint>
            <web-resource-collection>
                <web-resource-name>Wildcard means whole app requires authentication</web-resource-name>
                <url-pattern>/*</url-pattern>
                <http-method>GET</http-method>
                <http-method>POST</http-method>
            </web-resource-collection>
            <auth-constraint>
                <role-name>tomcat1</role-name>
            </auth-constraint>

            <user-data-constraint>
                <!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
                <transport-guarantee>NONE</transport-guarantee>
            </user-data-constraint>
        </security-constraint>

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

从浏览器调用REST URL工作正常。他询问用户和密码,然后显示REST服务的响应。

但是当我尝试使用以下snipplet从Javascript调用它时,我总是收到403错误并发出警告

OPTIONS http://localhost:10080/xxxx/rest/fileupload No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access

我正在使用的Code Snipplet:

xhr.open('POST', url, true);
//xhr.open("POST", url, true, "user1", "tomcat1");
xhr.setRequestHeader("Authorization","Basic "+ btoa("user1:tomcat1"));
xhr.withCredentials = "true";
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
            var jsonResponse = JSON.parse(xhr.responseText);

我做错了什么?我很困惑为什么现在添加身份验证后,浏览器抱怨没有访问控制标头存在。在向服务添加身份验证之前,该呼叫也适用于CORS。

我从HTTP请求中可以看到基本身份验证标头似乎设置正确。

    Request URL:http://localhost:10080/xxx/rest/fileupload
Request Method:OPTIONS
Status Code:403 Forbidden
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:authorization, content-type
Access-Control-Request-Method:POST
Authorization:Basic dXNlcjE6dG9tY2F0MQ==
Connection:keep-alive
Host:localhost:10080
Origin:http://localhost:63342
Referer:http://localhost:63342/xxx/html/index.html
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Response Headersview source
Content-Length:0
Content-Type:text/plain
Date:Thu, 05 Dec 2013 12:58:46 GMT
Server:Apache-Coyote/1.1

任何人都可以帮我理解我做错了什么。我很困惑,如果Tmocat配置是mssing或我的Javascript是错误的。

1 个答案:

答案 0 :(得分:2)

我不知道您是否设法解决了您的问题,但我遇到了同样的问题并通过org.apache.catalina.filters.CorsFilter进行了调试,以找出禁止请求的原因。

根据W3 CORS Spec Section 6.2 Preflight Requests,如果提交的标头与允许的标头不匹配,则预检必须拒绝该请求。

default configuration for the CorsFilter cors.allowed.headers(与您一样)不包含随请求提交的Authorization标头。

我更新了cors.allowed.headers过滤器设置以接受authorization标头,现在预检请求已成功。

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.headers</param-name>
        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
    </init-param>     
</filter>