与记住我持久性令牌的问题

时间:2013-07-03 09:56:54

标签: spring-security remember-me

在实现spring security remember-me持久性令牌时遇到问题。 已成功实现remember-me持久性令牌,但在用户注销系统时会出现问题。

以下是实施: 弹簧security.xml文件

    <global-method-security pre-post-annotations="enabled"/>

<http auto-config="true" use-expressions="true" >
    ...some url parten
    <form-login login-page="/login.html"
        authentication-failure-url="/loginfailed.html" 
        authentication-success-handler-ref="customAuthenticationHandler"/>
    <logout logout-success-url="/logout.html" delete-cookies='JSESSIONID' />
    <remember-me services-ref="pfRememberMeServices" 
                                        key="pf_token_key"/>
</http>

<beans:bean id="pfRememberMeServices" 
    class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
      <beans:property name="tokenRepository" ref="pfTokenRepository" />
      <beans:property name="userDetailsService" ref="userDetailsService" />
      <beans:property name="tokenValiditySeconds" value="86400"/> <!-- alive in 1 day -->
      <beans:property name="key" value="pf_token_key" />
      <beans:property name="cookieName" value="mycookie" />
      <beans:property name="alwaysRemember" value="true" />
 </beans:bean>

<authentication-manager alias="authenticationManager">
     <authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>

<beans:bean id="userDetailsService"
    class="com.platform.authenticate.model.UserDetailsServiceImpl" >
</beans:bean>.

令牌存储库:

    @Override
public void removeUserTokens(String userid) {
    // TODO Auto-generated method stub
    tokenDao.removeUserTokens(userid);
}

TokenDao:

    @Transactional
public void removeUserTokens(final String username) {
    //Session session = getSessionFactory().getCurrentSession();
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        Token token =
               (Token) session.createCriteria(Token.class)
                        .add(Restrictions.eq("username", username)).uniqueResult();
        if (token != null) {
            session.delete(token);
        }
        tx.commit();
    } catch (RuntimeException e) {
        tx.rollback();
        throw e; // or display error message
    } finally {
        session.close();
    }
}

当我在两个浏览器或两个客户端上使用同一用户登录时,persistent_logins表中有两条记录如下:

"2JLIh8E8vifKOdlaidCIog==";"user12";"OKjbqqIAhx74JpmPsNQHaw==";"2013-07-03 16:19:05.12"
"gQ2EDtl87ZC6XSjV6cTYrA==";"user12";"iYrG7dlnjPyKxUz/hwQMdQ==";"2013-07-03 15:47:24.011"

当同一个用户有两条记录时,我的实施是否正确?

然后,当我从一个浏览器或一个客户端注销时,会触发removeUserTokens()函数,但是:

    Token token =
           (Token) session.createCriteria(Token.class)
                    .add(Restrictions.eq("username", username)).uniqueResult();

使用上面的代码,我无法通过用户名删除注销用户的令牌,当有user12的2条记录时,它不是唯一的结果。

如果我强制删除所有user12,则将删除所有客户端的所有会话/令牌。这不对吗?

那么我怎样才能删除注销用户的会话/令牌信息,但是为其他客户端的同一用户保留会话/令牌?

我已经问过谷歌先生,但我的问题似乎很独特,找不到任何相同的。

如果我的实施有误,请告诉我。

更新 当我从一个客户端发送j_spring_security_logout时,这是堆栈跟踪:

  

例外

     

org.hibernate.NonUniqueResultException:查询没有返回唯一的   结果:2     org.hibernate.impl.AbstractQueryImpl.uniqueElement(AbstractQueryImpl.java:899)     org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:369)

1 个答案:

答案 0 :(得分:0)

我有同样的实现 - 我遇到了同样的问题。

但是我没有决定删除所有令牌,因为要查找令牌肯定是

    List<Token> tokens = sessionFactory.getCurrentSession().createCriteria(Token.class)
                    .add(Restrictions.eq("username", username)).list();
    if (tokens.size() > 0) {
        for (Token token : tokens) {
            sessionFactory.getCurrentSession().delete(token);
        }
    }