泽西岛:区分会话超时和缺乏授权

时间:2014-05-15 11:04:47

标签: java-ee exception tomcat jersey jax-rs

我使用Jersey(1.18.1)启用了RolesAllowedResourceFilterFactory。 假设我有以下资源:

@RolesAllowed("SuperUser")
@Path("/resource")
class Resource{
  //some code here
}

在会话超时时访问此资源时,服务器会抛出WebApplicationException而没有任何消息,但如果没有必要角色的用户尝试访问给定资源,它也会执行此操作。那么:如何区分会话超时和缺少必要的角色?

我需要这样做,因为我想发送一个适当的消息(从ExceptionMapper)到前端并在那里采取适当的措施。

2 个答案:

答案 0 :(得分:0)

我认为没有构建方法可以实现此目的,因为容器需要记住过期的sessionId及其关联用户。据我所知,容器只会在会话超时时删除此信息。 但你可以尝试自己做这件事:

实现HttpSessionListener并将过期的SessionID存储在某种缓存中。您很可能只想向授权用户显示此“会话过期”消息,但也可能为非授权用户创建HTTP会话。因此,您需要检查用户是否已获得授权。由于您无法访问SessionListener中的UserPrincipal,因此您需要自行在会话中存储一些信息。

@WebListener
public class HttpSessionChecker implements HttpSessionListener {

    @Inject
    private SessionIdCache cache;

    public void sessionCreated(HttpSessionEvent event) {}

    public void sessionDestroyed(HttpSessionEvent event) {
        if (event.getSession().getAttribute("someAuthInformation") != null) { // whatever you've stored
            cache.put(event.getSession().getId(), new Date());
        }
    }

}

在您的ExceptionMapper中,您现在可以检查JSESSIONID-Cookie是否是请求标头的一部分,以及是否在缓存中找到了传递的sessionID。

@Provider
public class ExMapper implements ExceptionMapper<Exception> { 

    @Inject
    private SessionIdCache cache;

    @Context 
    private HttpServletRequest request;

    @Override 
    public Response toResponse(Exception ex) { 
        for (Cookie cookie : request.getCookies()) {
            if ("JSESSIONID".equals(cookie.getName())) {
                String sessionId = cookie.getValue().substring(0, cookie.getValue().lastIndexOf('.')); // ignore .hostname
                if (cache.contains(sessionId)) {
                    return Response.serverError().entity("Your session timed out").build();
                }
            }
        }
        return Response.serverError().build();
    } 

}

您应该考虑不时清理缓存。

答案 1 :(得分:0)

我通过将SecurityContext注入ExceptionMapper并检查用户是否分配了任何角色来解决问题。如果它已经且webAppException.getResponse().getStatus()状态代码等于FORBIDDEN(403),那么异常的原因是缺乏授权(用户没有必要的角色)。如果用户没有任何已分配的角色,并且响应的状态代码再次为403 - 则表示会话已过期,否则其他原因是异常的原因。

这种方法有一个很大的缺点 - 它要求所有用户至少拥有一个指定的角色,否则它将无法工作;