我有一个用Jersey库实现的JAX-RS Web服务,现在我想测试它.为了做到这一点,我想通过使用模拟服务预先初始化我的测试来托管这项服务.
托管此类服务和执行测试调用的最佳方法是什么?
@Path("/srv")
public class MyService
{
@GET
public void action(@Context UriInfo uri)
{ ... }
}
@Test
public void myTest()
{
MyService service = new MyService();
service.setSomething(...);
// How do I host it?
// How do I call it?
}
Run Code Online (Sandbox Code Playgroud) 我有很多参数可以使用JAX-RS传递给服务器.
有没有办法通过URL传递或AarryList?
让我们/users/{id}成为RESTful服务中的资源URL.
启用基本身份验证,只允许经过身份验证的用户访问该URL.
示例场景:
User_1&User_2是使用userId 1和2的经过身份验证的用户.由于两者都经过身份验证,因此他们都可以访问,
/users/1/users/2但期望是User_1应该访问/users/1而不是/users/2或其他userId.
问题:如何在RESTful服务中进行资源级别授权?
注意:我正在使用Jax-RS(使用Apache CXF实现)实现RESTful,如果您可以使用Jax-RS进行解释,这将非常有用.
-Barath
编辑:
正如Donal所说,我不是在寻找基于角色的授权而是资源级授权.
举个例子,让/ users/{id}/photos/{photoId}成为另一个资源网址.User_1应该只能访问属于他的照片.如果photoId属于user_2,那么当请求request/users/1/photos/2时,我们应该为user_1提供http_404错误代码.[由于User_1也是经过身份验证的用户,他可以调用/ users/2/photos/2,所以我们必须根据认证参数识别用户ID,而不是通过资源url]
我能想到的唯一解决方案是,包括确定每个查询中授权的唯一ID,例如
代替 SELECT * FROM PHOTO_TBL WHERE PHOTO_ID=2;
使用 SELECT * FROM PHOTO_TBL, USER_TBL WHERE PHOTO_ID=2 AND USER_ID=1 AND USER_ID=PHOTO_ID;
使用此资源提供属于特定用户的数据.[应该有一种机制来阻止修改客户端中用于决定授权的唯一id(在本例中为userId),因为所有请求都是STATELESS请求]
警告:每个查询都应足够智能,以了解安全问题并包括额外的连接.这是一种将安全逻辑与每个业务功能联系起来的糟糕设计.
我还没有看看Spring的安全性以及如何在这个用例中使用它.
我正在使用Jersey JAX-RS客户端(版本2.0).我知道它使用Jackson ObjectMapper来生成和解析JSON.我想使用同一个对象为某些java类生成JSON,以便我可以将它们写入日志.
我知道我可以创建一个新的ObjectMapper实例,但我更愿意请求Jersey客户端给我一个它正在使用的实例.我怎样才能做到这一点?Jersey 2.0知道Jackson,因为它包含一个JacksonFeature类,用于首先配置Jackson功能.
假设我使用@GET方法调用以下Web服务:
@GET
@Path(value = "/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserCache(@PathParam("id") String id, @Context HttpHeaders headers) throws Exception {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", id);
SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
Cre8Mapper mapper = session.getMapper(Cre8Mapper.class);
// slow it down 5 seconds
Thread.sleep(5000);
// get data from database
User user = mapper.getUser(map);
if (user == null) {
return Response.ok().status(Status.NOT_FOUND).build();
} else {
CacheControl cc = new CacheControl();
// save data for 60 seconds
cc.setMaxAge(60);
cc.setPrivate(true);
return Response.ok(gson.toJson(user)).cacheControl(cc).status(Status.OK).build();
}
}
Run Code Online (Sandbox Code Playgroud)
为了实验,我在从数据库中获取数据之前5秒放慢当前线程的速度. …
是否有任何实现javax.ws.rs.core.UriInfo可用于快速创建实例以进行测试.这个界面很长,我只需要测试一下.我不想在这个界面的整个实现上浪费时间.
更新:我想为类似于此的函数编写单元测试:
@GET
@Path("/my_path")
@Produces(MediaType.TEXT_XML)
public String webserviceRequest(@Context UriInfo uriInfo);
Run Code Online (Sandbox Code Playgroud) 我有一个JAX-RS客户端正在做一个简单的GET请求.我正在使用CXF实现和Spring for DI.呼叫成功,我得到200响应代码.但是当我将反馈读入我的POJO时,我收到了一个错误.
例外:
[2015-05-08 16:11:55,457][ERROR][org.apache.cxf.jaxrs.utils.JAXRSUtils]: No message body reader has been found for class com.voya.refapp.domain.Customer, ContentType: application/json
[2015-05-08 16:11:55,468][ERROR][com.voya.refapp.service.CustomerServiceImpl]: filterByName() - Exception occurred
javax.ws.rs.client.ResponseProcessingException: No message body reader has been found for class com.voya.refapp.domain.Customer, ContentType: application/json
at org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:433) ~[cxf-rt-frontend-jaxrs-3.0.4.jar:3.0.4]
at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:384) ~[cxf-rt-frontend-jaxrs-3.0.4.jar:3.0.4]
Run Code Online (Sandbox Code Playgroud)
码:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/rest").path("customers/1");
Invocation.Builder builder = target.request(MediaType.APPLICATION_JSON_TYPE);
Response response = builder.get(); // Successful
Customer customer = response.readEntity(Customer.class); // Fails
Run Code Online (Sandbox Code Playgroud)
我在类路径中的答案中提出了以下依赖关系,它似乎没有自动获取.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我还尝试在创建客户端时注册json提供程序:
Client client = ClientBuilder.newClient().register(new …Run Code Online (Sandbox Code Playgroud) 我正在使用的API决定接受UUID作为Base32编码的字符串,而不是UUID.fromString()期望的标准十六进制,破折号分隔格式.这意味着我不能简单地写@QueryParam UUID myUuid为方法参数,因为转换会失败.
我正在解决这个问题,通过使用不同的fromString转换器编写自定义对象以与Jersey @QueryString和@FormParam注释一起使用.我希望能够访问fromString方法中的转换上下文,以便我可以提供更好的错误消息.现在,我所能做的就是以下几点:
public static Base32UUID fromString(String uuidString) {
final UUID uuid = UUIDUtils.fromBase32(uuidString, false);
if (null == uuid) {
throw new InvalidParametersException(ImmutableList.of("Invalid uuid: " + uuidString));
}
return new Base32UUID(uuid);
}
Run Code Online (Sandbox Code Playgroud)
我希望能够公开哪个参数具有无效的UUID,因此我记录的异常和返回的用户错误非常清楚.理想情况下,我的转换方法会有一个额外的参数用于细节,如下所示:
public static Base32UUID fromString(
String uuidString,
String parameterName // New parameter?
) {
final UUID uuid = UUIDUtils.fromBase32(uuidString, false);
if (null == uuid) {
throw new InvalidParametersException(ImmutableList.of("Invalid uuid: " + uuidString
+ …Run Code Online (Sandbox Code Playgroud) jax-rs ×10
java ×5
jersey ×3
rest ×3
jackson ×2
annotations ×1
arrays ×1
clojure ×1
cxf ×1
grizzly ×1
http ×1
http-caching ×1
jersey-2.0 ×1
json ×1
junit ×1
testng ×1
unit-testing ×1
web-services ×1