Java 使用 Apache Shiro 登录身份验证休眠 "successfully" 登录后返回 false
Java hibernate with Apache Shiro login authentication returning false after "successfully" logging in
我正在使用 Java Hibernate 和 Apache Shiro 进行用户登录和身份验证。我使用此代码对用户进行身份验证并且它按预期工作(据我所知)。
try {
AuthenticationToken token = new UsernamePasswordToken(user.getUsername().toUpperCase(), user.getPassword());
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
session.setAttribute( "username", user.getUsername());
System.out.println("USER: " + session.getAttribute("username"));
currentUser.login(token);
System.out.println( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
System.out.println( "Is user authenticated? " + currentUser.isAuthenticated());
}
catch (ExcessiveAttemptsException eae ) {
eae.getStackTrace();
eae.printStackTrace();
}
catch (AuthenticationException e) {
throw new ForbiddenException();
}
如果提供了正确的凭据,则此方法有效;如果提供的凭据不正确,则 return 禁止例外。
在我使用另一种方法检查用户是否获得授权后,但它总是 returns false(当它应该是 true 时)。我不确定是什么原因造成的。
try {
Subject currentUser = SecurityUtils.getSubject();
return SecurityUtils.getSubject().isAuthenticated();
} catch (AuthenticationException e) {
throw new ForbiddenException();
}
在调试模式下检查时,currentUser 为空。
我也可以使用另一种方法,但它 return 在第二行出现 nullPointerException。
try {
sessionFactory.getCurrentSession().getTransaction().begin();
User user = userDAO.find(securityContext.getUserPrincipal().getName());
if (user == null) {
sessionFactory.getCurrentSession().getTransaction().rollback();
throw new NotFoundException();
}
UserModel result = new UserModel(user);
sessionFactory.getCurrentSession().getTransaction().commit();
return result;
}
} catch (HibernateException e) {
e.printStackTrace();
sessionFactory.getCurrentSession().getTransaction().rollback();
}
return null;
我使用 shiro.ini 连接到本地数据库。
[更新] 我已经添加了一个调试登录过滤器,它可以在启用时自动登录(使用 Servlet)并且它按预期工作。
我添加了一个 URL 部分,当我使用 authcBasic 时它有效,但当我在 Shiro 中使用 authc 时它不起作用。我可以通过调用方法 isAuthenticated()
或 getCurrentUser()
来检查。使用 authcBasic returns 所有正确的信息,但 authc returns false/null。除非我清理网络浏览器,否则我在使用 authcBasic 时也无法注销。 SecurityUtils.getSubject().logout();
方法将 isAuthenticated 布尔值设置为 false(当我调试时)但似乎对会话没有任何实际影响。
# =======================
# Shiro INI configuration
# =======================
[main]
# Debug filter to automatically login
debugLogin = util.DebugLoginFilter
debugLogin.enabled = false
debugLogin.username = ADMIN
debugLogin.password = ADMIN
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.authenticationQuery = select password from user where username = ?
jdbcRealm.userRolesQuery = select role from user_role INNER JOIN user ON user_role.id = user.user_role_id where user.username = ?
# Datasource for the jdbc realm
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = localhost
ds.user = root
ds.databaseName = database
jdbcRealm.dataSource = $ds
authc.usernameParam = username
authc.passwordParam = password
authc.failureKeyAttribute = shiroLoginFailure
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
jdbcRealm.credentialsMatcher = $sha256Matcher
[roles]
admin = *
[urls]
/ = debugLogin, authcBasic
/index.html = debugLogin, authcBasic
/api/login = anon
/api/login/me = authcBasic
/api/login/logout = authcBasic
/api/** = debugLogin, authcBasic
我的pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
我的web.xml
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
如果我犯了任何错误,我深表歉意,我是新来的!任何帮助将不胜感激。
编辑:当 运行 Apache 服务器:
时,此消息显示在控制台中
[localhost-startStop-1] INFO org.apache.shiro.config.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
我找到了解决办法。问题不在于代码,而在于我使用的方法。
我为 front-end 使用 Angular 2,为 back-end 使用 Java Hibernate。 Shiro 无法与 front-end 通信,因为它在不同的目录中。但它在构建 angular 应用程序并将 dist 内容复制到 back-end.
中的 WebContent 后可以正常工作
我将在开发时使用调试登录过滤器手动登录(然后在 Shiro 准备好生产后将其禁用)。
我会保留代码片段以防其他人遇到此问题。
我正在使用 Java Hibernate 和 Apache Shiro 进行用户登录和身份验证。我使用此代码对用户进行身份验证并且它按预期工作(据我所知)。
try {
AuthenticationToken token = new UsernamePasswordToken(user.getUsername().toUpperCase(), user.getPassword());
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
session.setAttribute( "username", user.getUsername());
System.out.println("USER: " + session.getAttribute("username"));
currentUser.login(token);
System.out.println( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
System.out.println( "Is user authenticated? " + currentUser.isAuthenticated());
}
catch (ExcessiveAttemptsException eae ) {
eae.getStackTrace();
eae.printStackTrace();
}
catch (AuthenticationException e) {
throw new ForbiddenException();
}
如果提供了正确的凭据,则此方法有效;如果提供的凭据不正确,则 return 禁止例外。
在我使用另一种方法检查用户是否获得授权后,但它总是 returns false(当它应该是 true 时)。我不确定是什么原因造成的。
try {
Subject currentUser = SecurityUtils.getSubject();
return SecurityUtils.getSubject().isAuthenticated();
} catch (AuthenticationException e) {
throw new ForbiddenException();
}
在调试模式下检查时,currentUser 为空。
我也可以使用另一种方法,但它 return 在第二行出现 nullPointerException。
try {
sessionFactory.getCurrentSession().getTransaction().begin();
User user = userDAO.find(securityContext.getUserPrincipal().getName());
if (user == null) {
sessionFactory.getCurrentSession().getTransaction().rollback();
throw new NotFoundException();
}
UserModel result = new UserModel(user);
sessionFactory.getCurrentSession().getTransaction().commit();
return result;
}
} catch (HibernateException e) {
e.printStackTrace();
sessionFactory.getCurrentSession().getTransaction().rollback();
}
return null;
我使用 shiro.ini 连接到本地数据库。
[更新] 我已经添加了一个调试登录过滤器,它可以在启用时自动登录(使用 Servlet)并且它按预期工作。
我添加了一个 URL 部分,当我使用 authcBasic 时它有效,但当我在 Shiro 中使用 authc 时它不起作用。我可以通过调用方法 isAuthenticated()
或 getCurrentUser()
来检查。使用 authcBasic returns 所有正确的信息,但 authc returns false/null。除非我清理网络浏览器,否则我在使用 authcBasic 时也无法注销。 SecurityUtils.getSubject().logout();
方法将 isAuthenticated 布尔值设置为 false(当我调试时)但似乎对会话没有任何实际影响。
# =======================
# Shiro INI configuration
# =======================
[main]
# Debug filter to automatically login
debugLogin = util.DebugLoginFilter
debugLogin.enabled = false
debugLogin.username = ADMIN
debugLogin.password = ADMIN
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.authenticationQuery = select password from user where username = ?
jdbcRealm.userRolesQuery = select role from user_role INNER JOIN user ON user_role.id = user.user_role_id where user.username = ?
# Datasource for the jdbc realm
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = localhost
ds.user = root
ds.databaseName = database
jdbcRealm.dataSource = $ds
authc.usernameParam = username
authc.passwordParam = password
authc.failureKeyAttribute = shiroLoginFailure
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
jdbcRealm.credentialsMatcher = $sha256Matcher
[roles]
admin = *
[urls]
/ = debugLogin, authcBasic
/index.html = debugLogin, authcBasic
/api/login = anon
/api/login/me = authcBasic
/api/login/logout = authcBasic
/api/** = debugLogin, authcBasic
我的pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
我的web.xml
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
如果我犯了任何错误,我深表歉意,我是新来的!任何帮助将不胜感激。
编辑:当 运行 Apache 服务器:
时,此消息显示在控制台中[localhost-startStop-1] INFO org.apache.shiro.config.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
我找到了解决办法。问题不在于代码,而在于我使用的方法。
我为 front-end 使用 Angular 2,为 back-end 使用 Java Hibernate。 Shiro 无法与 front-end 通信,因为它在不同的目录中。但它在构建 angular 应用程序并将 dist 内容复制到 back-end.
中的 WebContent 后可以正常工作我将在开发时使用调试登录过滤器手动登录(然后在 Shiro 准备好生产后将其禁用)。
我会保留代码片段以防其他人遇到此问题。