3

我在实现 spring security 时遇到了一个问题,记住我的持久性令牌。已经成功实现了记住我的持久令牌,但是当用户注销系统时出现问题。

这里是实现:spring-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);
}

通证道:

    @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)

4

1 回答 1

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);
        }
    }
于 2014-01-30T08:29:44.067 回答