Liferay:允许远程访问 JSON Web 服务

Liferay: Allow remote access to JSON Web Services

我正在尝试从同一台机器访问 Liferay 提供的 JSON Web 服务的不同端口。

我在 portal-ext.properties 文件中设置了以下属性:

json.servlet.hosts.allowed=127.0.0.1
auth.token.check.enabled=true
jsonws.servlet.https.required=false
json.web.service.enabled=true
axis.servlet.hosts.allowed=127.0.0.1
json.service.auth.token.hosts.allowed=127.0.0.1

我还从 $LIFERAY_HOME/tomcat-8.0.32/webapps/ROOT/WEB-INF/web.xml 配置了 web.xml 文件并添加了以下内容,尽管在论坛的一些帖子中说没有必要:

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

我可以使用 curl 访问端点,但我不能从另一个端口的应用程序 运行 访问,我收到以下错误:

 Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Javascript中执行请求的代码如下:

var url = `http://127.0.0.1:8080/api/jsonws/user/get-user-by-email-address/?companyId=20116&emailAddress=test%liferay.com&p_auth=${key}`;

var data = null;

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener('readystatechange', function () {
  if (this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open('GET', url);
xhr.setRequestHeader('authorization', 'Basic Y2FsYmVyY2FAYXV0ZW50aWEuY29tOnRlc3Q=');
xhr.setRequestHeader('cache-control', 'no-cache');

xhr.send(data);

我认为这与 portal-ext.properties 配置有关,也许与端口有关。有什么想法吗?

这不是真正的 Liferay 配置错误,而是浏览器安全相关问题,称为 CORS(Cross-Origin 资源共享)。您可以阅读更多关于它的内容 here 但总的来说,它归结为这样一个事实,即为了 site Asite B 加载资源(这实际上是 XMLHttpRequest 所做的), site B 需要通过特殊 header!

指定资源对 site A 可用

Liferay 显然不会这样做,因为它无法知道您将从哪里消耗资源。对于你正在尝试做的工作,你需要创建并部署到 Liferay 一个 servlet 过滤器,你可以在其中自己添加适当的 headers。此类过滤器的示例可用 here

我决定采用的方法是创建一个 OSGi module using the blade cli provided by Liferay to scaffold a rest service (blade.rest) with Jax-RS (As explained here)。从那里我配置了 CXF 端点和 REST Extender。然后我将 UsersRestService class 修改为以下内容:

package com.liferay.blade.samples.rest;

import com.liferay.portal.kernel.service.UserLocalService;

import java.util.Collections;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

@ApplicationPath("/blade.users")
@Component(
    immediate = true, property = {"jaxrs.application=true"},
    service = Application.class
)
public class UsersRestService extends Application {

    @Override
    public Set<Object> getSingletons() {
        return Collections.singleton(this);
    }

    @GET
    @Path("/list")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUsers() {
        String json = "{\n" + "  \"value\": \"cool\"\n" + "}";
        return Response
                .status(200)
                .entity(json)
                .build();
    }

    @Reference
    private volatile UserLocalService _userLocalService;

}

在此 class 中,您可以访问 Liferay 的服务,因此您可以向 API 其他人公开您想要的内容。

我要检查的最后一件事是 "Access-Control-Allow-Origin" 属性,因为它似乎在某处已分配但我不知道在哪里。