4

我正在为安全性实施 java shiro。我需要在会话过期时返回消息,如果会话未过期,那么我需要返回不同的消息,例如 un Authenticate user。

这是我的代码。

@GET
@Path("/{userId}")
public Response view(@PathParam("userId")String userId)
{
   ResponseBuilder builder = Response.ok();
   if(SecurityUtils.getSubject().isAuthenticated())
    {

       Registeration registeration=new Registeration();
       boolean status=registeration.getDetails(userId,builder);
       log.debug("the status is:"+status); 


    }
    else
    {
        builder.status(401).entity("You are currently not login .please Login for Access Services");

    }   
    return builder.build();     

}

以上休息服务工作正常。当用户未登录时。此方法将返回其他部分的消息。但我还需要返回消息,在会话过期并且用户尝试访问此休息服务之后,我需要返回“您的会话已过期”。但在上述情况下,如果会话过期,则消息相同,如果用户未登录,则消息也相同。我不知道我将如何检查这两个条件:1)如果用户未登录,则消息 =“您正在登录”2)如果会话已过期,则消息 =“您的会话已过期”

4

1 回答 1

2

经过一些简单的测试,我相信SecurityUtils.getSubject().isAuthenticated()当前会话超时时使用的方式无法得到正确的结果。我想它对您有用,因为第二个请求Subject为您创建了另一个请求,而不是原始请求。这可以很容易地通过获取它来证明,ThreadContext.getSubject()而不是SecurityUtils.getSubject()因为后者Subject为你创建一个新的,如果它是空的。如果第二次请求到达您的方法并且返回值为ThreadContext.getSubject()null,则意味着它是与 Shiro 的新线程的新连接。

因此,我的测试结果表明,如果是“超时”情况,Subject.isAuthenticated()仍然会返回 true。注意他们的文档Session Validation & Scheduling

出于性能原因,仅验证会话以查看它们在访问时是否已停止或过期(即 subject.getSession())。这意味着如果没有额外的定期验证,会话孤儿将开始填满会话数据存储。

根据您的要求,您可以实现 aSessionListener并将主体记录在 method 中onExpiration。或者您可以访问会话以触发 Shiro 中的验证:

if(SecurityUtils.getSubject().isAuthenticated()) {
    Session session = SecurityUtils.getSubject().getSession(false);
    try {
        session.touch();
    } catch (ExpiredSessionException e) {
        // timeout case.
    }
} else {
    // not login case.
}

调用session.touch()不是多余的,因为它会更新lastAccessTime,如果您从不接触代码中的会话,则不会这样做。

于 2014-01-16T07:13:51.777 回答