当前位置: 首页 > 知识库问答 >
问题:

Apache Shiro身份验证第二次失败

公羊向荣
2023-03-14

我有一个JavaEE web应用程序,它使用ApacheShiro作为安全框架。我已经实现了一个自定义JPA授权域,这样我就可以使用JPA存储我的用户帐户。我的自定义域看起来像这样。。。

public class JPAAuthorizingRealm extends AuthorizingRealm {

    /**
     * Logger for this class
     */
    private static final Logger logger = Logger
            .getLogger(JPAAuthorizingRealm.class);

    public static final String REALM_NAME = "jpaRealm";

    private UserAccountRepository accountRepository = null;

    @SuppressWarnings("unchecked")
    public JPAAuthorizingRealm() {
        super();

        setName("JpaRealm");
        setAuthenticationCachingEnabled(false);
        setCachingEnabled(false);

        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("SHA-256");
        matcher.setHashIterations(SecurityConstants.PASSWORD_HASH_ITERATIONS);
        setCredentialsMatcher(matcher);

        try {
            BeanManager beanManager = (BeanManager) new InitialContext()
                    .lookup("java:comp/BeanManager");
            Bean<UserAccountRepository> accountRepositoryBean = (Bean<UserAccountRepository>) beanManager
                    .resolve(beanManager.getBeans(UserAccountRepository.class));
            CreationalContext<?> creationalContext = beanManager
                    .createCreationalContext(null);
            UserAccountRepository accountRepository = accountRepositoryBean
                    .create((CreationalContext<UserAccountRepository>) creationalContext);
            this.accountRepository = accountRepository;
        } catch (NamingException e) {
            logger.error(
                    "JPAAuthorizingRealm() - exception while creating user account repository", e); //$NON-NLS-1$
        }
    }

  <snip>

我能够成功地创建用户帐户(在一个单独的类中),并使用一个可用于身份验证的哈希密码。我的问题是,我只能验证一次。如果我登录一个用户,我会看到我的Shiro主题说我已通过身份验证。但是,如果我注销,并尝试使用完全相同的凭据(甚至完全不同的帐户)重新登录,则登录似乎永远不会被应用。我看到我的主题在身份验证后立即具有isAuthenticated()==true,但在后续请求中,它会显示isAuthenticated()==false。即使我打开一个完全独立的浏览器,我也会看到同样的行为。一旦我的第一个用户成功登录,我就无法登录第二个用户。

我的登录代码如下所示,并在无状态EJB中实现。。。

AuthenticationToken token = new UsernamePasswordToken(loginName,
        password);
try {
    this.subject.login(token);
} catch (IncorrectCredentialsException e) {
    logger.error("authenticateUser(String, String)", e); //$NON-NLS-1$

    throw new InvalidCredentialsException(e);
} catch (AuthenticationException e) {
    logger.error("authenticateUser(String, String)", e); //$NON-NLS-1$

    throw new UserAuthenticationException(e);
}

我的注销代码如下所示。。。

SecurityUtils.getSubject().logout();
Faces.invalidateSession();

我的shiro.ini文件是这样的:

[main]
# listener = org.apache.shiro.config.event.LoggingBeanListener

authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
authc.loginUrl = /login.xhtml

jpaRealm=com.myapp.JPAAuthorizingRealm

[urls]
/login.xhtml = authc

再一次,当我第一次进行身份验证时,一切正常。我的当事人说我每一个请求都经过认证。如果我打开一个单独的浏览器并尝试作为第二个用户进行身份验证,则身份验证永远不会通过。你知道这是什么原因吗?我对ApacheShiro有些陌生,所以完全有可能我做错了什么。

更新:我已经做了更多的测试,并用标准的Shiro JDBC领域替换了我的自定义JPA领域,只是为了缩小问题所在。新的JDBC领域配置导致与以前完全相同的行为。然而,我现在注意到,如果我从浏览器A以用户1的身份登录(Safari,登录成功)成功,然后尝试在另一个浏览器上以用户2的身份登录(火狐,登录似乎不成功),然后回到浏览器A并点击刷新,我看到自己认证为用户1。似乎有某种国家管理问题在发生,但我一生都想不明白是什么。

这是我的新雪罗。ini,以及用于生成Subject和SecurityManager对象的CDI生成器。有人能帮我解决这个问题吗?这很令人沮丧。

shiro.ini:

[main]
hashService=org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations=10000
hashService.hashAlgorithmName=SHA-256

passwordService=org.apache.shiro.authc.credential.DefaultPasswordService
passwordService.hashService = $hashService

passwordMatcher=org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService=$passwordService

authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
authc.loginUrl = /login.xhtml

jdbcDataSource=org.apache.shiro.jndi.JndiObjectFactory
jdbcDataSource.resourceName=java:jboss/datasources/MyDataSource
jdbcDataSource.resourceRef=true

jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.authenticationQuery = SELECT hashedPassword FROM tbl_user_account WHERE loginname = ?
jdbcRealm.permissionsLookupEnabled=false
#jdbcRealm.credentialsMatcher = $sha256Matcher
jdbcRealm.credentialsMatcher=$passwordMatcher
jdbcRealm.dataSource = $jdbcDataSource

securityManager.realms = $jdbcRealm

[urls]
/login.xhtml = authc

CDI制作人:

@Singleton
public class SecurityProducer {

    /**
     * Logger for this class
     */
    private static final Logger logger = Logger
            .getLogger(SecurityProducer.class);

    private org.apache.shiro.mgt.SecurityManager securityManager;

    /**
     * Initializes the {@link org.apache.shiro.mgt.SecurityManager} after bean
     * creation
     */
    @PostConstruct
    public void init() {
        if (logger.isDebugEnabled()) {
            logger.debug("init() - start"); //$NON-NLS-1$
        }

        final String iniFile = "classpath:shiro.ini";
        securityManager = new IniSecurityManagerFactory(iniFile).getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        if (logger.isDebugEnabled()) {
            logger.debug("init() - end"); //$NON-NLS-1$
        }
    }

    /**
     * Produces an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager}
     * 
     * @return The security manager
     */
    @Produces
    @Named("securityManager")
    public org.apache.shiro.mgt.SecurityManager getSecurityManager() {
        if (logger.isDebugEnabled()) {
            logger.debug("getSecurityManager() - start"); //$NON-NLS-1$
        }

        if (logger.isDebugEnabled()) {
            logger.debug("getSecurityManager() - end"); //$NON-NLS-1$
        }
        return securityManager;
    }

    /**
     * Produces an Apache Shiro {@link Subject}
     * 
     * @return The subject
     */
    @Produces
    @Named("subject")
    public Subject getSubject() {
        if (logger.isDebugEnabled()) {
            logger.debug("getSubject() - start"); //$NON-NLS-1$
        }

        Subject subject = SecurityUtils.getSubject();
        if (logger.isDebugEnabled()) {
            logger.debug("getSubject() - Subject subject=" + subject); //$NON-NLS-1$
        }

        if (subject.isAuthenticated() || subject.isRemembered()) {
            boolean authenticated = subject.isAuthenticated();
            boolean remembered = subject.isRemembered();
            Object principal = subject.getPrincipal();
            if (logger.isDebugEnabled()) {
                logger.debug("getSubject() - authenticated=" + authenticated + ", remembered=" + remembered + ", principal=" + principal); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("getSubject() - User is not authenticated or remembered"); //$NON-NLS-1$
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("getSubject() - end"); //$NON-NLS-1$
        }
        return subject;
    }
}

共有2个答案

金理
2023-03-14

我也遇到了同样的问题,我通过在浏览器上清除本地主机(或任何服务器地址)的缓存和cookie来简单地解决了这个问题。上面的建议对我都不起作用。

毋承基
2023-03-14

在你的西罗。ini设置web会话管理器并将其设置到安全管理器中。看看这有什么帮助。

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
 类似资料:
  • Tweepy API请求twitter return me Twitter错误响应:状态代码=401。 这是我的实际代码: 我曾试图用tweepy软件包删除推文,并获得了所有必需的密钥。镊子包装不起作用吗?有人能帮我解决这个问题吗。

  • 在我的应用程序中,用户注册和认证使用Firebase。应用程序中的所有活动只对经过身份验证的用户开放。但在应用程序内部,有一个活动(ActivityB)是基于用户的数据。此活动再次限制了电子邮件和密码登录(以便没有安装该应用程序的人可以从其他用户检查此活动)。 即使User1/User2从ActivityB签名,user也是从整个firebase身份验证签名。 我所给的只是指示命令。但不管用

  • 问题内容: 尝试使用JavaMail中的NTLM连接到Exchange服务器。我可以连接到SMTP,但不能连接到IMAP。我还可以使用相同的主机/用户名/密码通过OS X Mail.app应用程序进行身份验证,帐户类型=“ IMAP”,端口143,ssl = false,authentication = NTLM,域名=“。 连接代码: 输出: 我尝试通过http://www.oracle.com

  • 我相对来说是JMeter的新手,但是我很难让HTTP Sampler登陆到一个安全的网页上。我认为它需要NTLM认证,所以我使用HTTP授权管理器来传递BlazeMeter指南中指定的凭证 我的授权管理器具有以下值: 基本网址: https:// [测试站点] 用户名: [我的用户名] 密码: [我的密码] 域:与基本网址相同 机制: BASIC_DIGEST 然而,我只是得到一个401错误(见下

  • 嗨,我正在尝试做一个手机身份验证在android使用Firebase。第一次我安装应用程序,短信来和验证是成功的,但随后短信没有再来。我已经从firebase的身份验证中删除了该用户,但它仍然不起作用。 下面是我的代码。

  • http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd“>