Restlet CorsFilter 与 ChallengeAuthenticator
Posted
技术标签:
【中文标题】Restlet CorsFilter 与 ChallengeAuthenticator【英文标题】:Restlet CorsFilter with ChallengeAuthenticator 【发布时间】:2015-01-28 15:44:10 【问题描述】:我正在使用 Restlet 框架构建一个 RESTful API,并且需要它来处理跨域调用 (CORS) 以及基本身份验证。
目前我正在使用CorsFilter,它可以让我的网络服务支持 CORS 请求。但是,当我尝试将它与带有 HTTP 基本身份验证的简单 ChallengeAuthenticator 一起使用时,它不会像我想要的那样工作(来自网站)。
当我通过 Chrome 直接访问网络服务时,它按预期工作,但是当我在一个用 angularjs (jquery/javascript) 编写的小型网络应用程序中尝试它并尝试访问网络服务时它没有。
基本上发生的情况是,当一个 OPTIONS 请求发送到我的网络服务时,它不会响应标题:“Access-Control-Allow-Origin”、“Access-Control-Allow-Credentials”等,因为它应该.相反,它发送一个带有 HTTP 状态代码 401 的响应,说明身份验证失败。这是因为身份验证器以某种方式覆盖了 CorsFilter 吗?
我的 createInboundRoot 方法如下所示。
@Override
public Restlet createInboundRoot()
ChallengeAuthenticator authenticator = createAuthenticator();
RoleAuthorizer authorizer = createRoleAuthorizer();
Router router = new Router(getContext());
router.attach("/items", ItemsServerResource.class);
router.attach("/items/", ItemsServerResource.class);
Router baseRouter = new Router(getContext());
authorizer.setNext(ItemServerResource.class);
authenticator.setNext(baseRouter);
baseRouter.attach("/items/itemID", authorizer);
baseRouter.attach("", router);
// router.attach("/items/itemID", ItemServerResource.class);
CorsFilter corsFilter = new CorsFilter(getContext());
corsFilter.setNext(authenticator);
corsFilter.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsFilter.setAllowedCredentials(true);
return corsFilter;
(授权者和认证者代码取自“官方”restlet指南进行授权和认证)
我已经尝试对我的代码进行很多更改,但没有一个能给我带来任何运气。但我注意到,当将 ChallengeAuthenticator 中的“可选”参数设置为 true("Indicates if the authentication success is optional")时,CorsFilter 完成了它的工作,但显然 ChallengeAuthenticator 并不关心对客户端进行身份验证,而是让任何东西使用受保护的资源..
有人遇到过类似的问题吗?或者您是否以任何其他方式解决了这个问题(CORS + Restlet 中的身份验证)?
提前致谢!
【问题讨论】:
这是我在 Chrome 中查看时看到的错误消息(其中 Origin 是托管 Web 应用程序的 Web 服务器的 ip):“不存在 'Access-Control-Allow-Origin' 标头在请求的资源上。因此不允许访问源“...”。响应的 HTTP 状态代码为 401。” 【参考方案1】:我认为这是 Restlet CORS 过滤器的错误。事实上,过滤器使用afterHandle
方法设置CORS 标头。源码见:https://github.com/restlet/restlet-framework-java/blob/4e8f0414b4f5ea733fcc30dd19944fd1e104bf74/modules/org.restlet/src/org/restlet/engine/application/CorsFilter.java#L119。
这意味着 CORS 处理是在执行整个处理链(身份验证,...)之后完成的。因此,如果您的身份验证失败,您将获得状态码 401。实际上是这种情况,因为 CORS 预检请求不会发送身份验证提示。
有关在 Restlet 中使用 CORS 的更多详细信息,您可以查看此链接:https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/。这可以为您提供一种解决方法,直到此错误在 Restlet 本身中得到修复。
我在 Github 中为您的问题打开了一个问题:https://github.com/restlet/restlet-framework-java/issues/1019。
希望对你有帮助, 蒂埃里
【讨论】:
感谢您的回答! (不幸的是,我不能投票给你的答案。)然后我会看看实现我自己的自定义“CorsFilter”,看看我是否可以摆脱这个错误:) 是的,没问题.. 它现在看起来就像一个魅力!你的实现,来自你的博客,正是我所需要的。再次感谢 很高兴听到它解决了您的问题。我联系了提供 cors 过滤器的人以找到问题的解决方案。请继续关注 ;-)【参考方案2】:CorsService(明天将在 2.3.1 中推出)还包含一个 skippingResourceForCorsOptions 属性,它直接回答 Options 请求,而不将请求传输到底层过滤器和服务器资源。
【讨论】:
以上是关于Restlet CorsFilter 与 ChallengeAuthenticator的主要内容,如果未能解决你的问题,请参考以下文章
Restlet 2.0.8:单个restlet应用程序实例的多种身份验证方法(BASIC、DIGEST)?
restlet 2.3.5 org.restlet包导入eclipse出现的com.sun.net.httpserver类包找不到问题