Apache Shiro:使用用户名/密码进行身份验证,但将用户ID存储为主体

时间:2014-02-23 09:54:03

标签: java authentication shiro

我开始使用Apache Shiro。我从简单的例子开始,并且在我去的时候一直在增加复杂性。

目前,我正在使用JSF从登录表单中收集电子邮件地址和密码,并使用UsernamePasswordToken通过Shiro对用户进行身份验证。

UsernamePasswordToken token = new UsernamePasswordToken(email, password);
SecurityUtils.getSubject().login(token);

由具有简单查询的现成JDBC领域支持

jdbcRealm.authenticationQuery = SELECT password FROM user WHERE email = ?

要获得有关用户的更多详细信息,例如他们的姓名,我将通过委托人在数据库中查找用户 - 这是他们的电子邮件地址。

currentUser = userDAO.findByEmail((String) SecurityUtils.getSubject().getPrincipal());

这很有效,但允许用户更改其电子邮件地址,这将破坏查找。我的目标是将唯一用户ID存储为主体而不是电子邮件地址,因为这永远不会改变。我将如何实现这一目标?

1 个答案:

答案 0 :(得分:1)

我最终用一种简单的方法解决了这个问题 - 在创建身份验证令牌之前从电子邮件地址转换为用户ID,并使用用户ID作为令牌中的主体。

try{
    // Lookup the user by email
    User user = userDAO.findByEmail(email);

    // If no match we can't authenticate
    if(user == null){
        throw new AuthenticationException();
    }

    // Else, build a token with the user id and password
    UsernamePasswordToken token = new UsernamePasswordToken(user.getUserId().toString(), password);

    // Attempt to login
    SecurityUtils.getSubject().login(token);

}catch(AuthenticationException ex){
    return false;
}

我的UserDAO bean配置为处理javax.persistence.NoResultException并返回null。

在我的shiro.ini文件中,我已将jdbcRealm.authenticationQuery更改为以下内容(注意我使用的是MySQL)

jdbcRealm.authenticationQuery = SELECT password FROM user WHERE user_id = CAST(? AS UNSIGNED)

最后,要查找有关用户的详细信息,我现在通过用户ID查找,现在是用户ID。

currentUser = userDAO.findByUserId(Integer.parseInt((String) SecurityUtils.getSubject().getPrincipal()));