我的应用程序具有一些可供所有用户访问的功能,以及一些其他功能,访问权限仅限于经过身份验证的用户。所有这些受限制的功能都存在于某些GWT场所中,因此,应用程序中可用的所有场所可以分为两组:“全民可访问”和“受限制”。在我看来,访问受限的地方可以实现一些界面(假设它会是RestrictedAccess
),如果用户继续其中一个,并且尚未经过身份验证,它将被重定向到登录屏幕 - 它比在URL上应用过滤器更为OO方法。
我想要实现的目标是:
到目前为止,我已经介绍了RestrictedAccess
接口,它由一些地方实现。我传递给FilteredActivityMapper包装应用程序活动映射器的FilteredActivityMapper.Filter
实现具有以下逻辑:
Place filter(Place place) {
if (place instanceof RestrictedAccess && !userHasBeenAuthenticated()) {
return new LoginPlace();
}
// return the original place - user has been already authenticated or
// place is accesible for all users
return place;
}
private boolean userHasBeenAuthenticated() {
// remote call - how to do ???
}
问题在于userHasBeenAuthenticated()
方法(如果已经过身份验证,则不应将用户重定向到LoginPlace)。如果我想在服务器端存储这些信息,我必须在这里进行GWT RPC /请求工厂调用,但两者都是异步的,所以我不能在filter
方法中处理它的结果。
我知道我可以使用web.xml过滤器或一些外部框架(例如Spring安全性),但这种方法都不允许我将登录页面作为基于标准GWT的表单,或以更多OO方式指示应限制进入某个地方。
提前感谢任何提示
编辑:我开始想知道是否应该在客户端进行过滤(限制/不受限制)。如果按照建议,有可能破解指示用户是否已经过身份验证的代码,则还有可能破解位置过滤代码,以便可以在不登录的情况下访问受限制的位置。
答案 0 :(得分:3)
Piotrek,
我认为调用userHasBeenAuthenticated()存在安全问题 - 每次调用此函数时,都可以破解客户端代码返回true。
我实现的解决方案是,如果未经身份验证的用户尝试访问任何远程服务,则只返回SC_UNAUTHORIZED。我已经覆盖了RequestFactory onResponseReceived函数,如果响应是SC_UNAUTHORIZED,它会重定向到登录页面。想法取自: http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/expenses/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
这适用于我们的情况,其中活动和地点都是以数据为中心的 - 每个地点更改都从服务器检索数据。如果用户未经过身份验证,则他们只是无法获取数据并被重定向到登录页面。
我意识到您的情况略有不同,因为每个人都可以访问某些地方,在这种情况下,您只能配置受限制的服务以返回SC_UNAUTHORIZED。
答案 1 :(得分:2)
我有类似的应用程序具有相同的要求。到目前为止,我还没有完成实施,但我的想法是一致的。
我计划做的是将身份验证状态客户端存储在AuthenticationManager类中。当应用程序启动时,我将从服务器请求登录信息(我正在考虑在应用程序引擎上运行,因此我将获得身份验证状态并获得开放ID登录/注销URL)并将其存储在AuthenticationManager中。 Acegi / Spring Security以类似的方式工作,因此如果您也使用这些信息,则可以在服务器端获得此信息。
当用户登录/注销时,它们将被服务器重定向,并且将检索新状态。这应该使客户端身份验证状态与服务器保持一致。还必须检查服务器上的每个RPC请求以进行身份验证。我正在使用gwt-dispacth库,这也有一些基本的身份验证检查和跨站点脚本保护(虽然我认为最新的GWT有这个用于通用RPC)。
一个问题是会话超时。 gwt-dispath库再次有一些代码可以检测到这一点,并将会话过期的异常返回给客户端,可以拦截这些异常并更新auth管理器。
希望有道理。