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 A
从 site 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" 属性,因为它似乎在某处已分配但我不知道在哪里。
我正在尝试从同一台机器访问 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 A
从 site 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" 属性,因为它似乎在某处已分配但我不知道在哪里。