shiro 授权过滤器被多次调用
shiro authorization filter getting called multiple times
我使用 apache shiro 和 google oauth 和 microsoft 365 oauth 编写了一个身份验证和授权模块。它允许用户使用那里的 google/ms 凭据登录没问题,但是授权过滤器被调用了很多次。下面是我从一次登录中获得的调试日志的示例。授权周期被调用了很多次。那么任何人都可以知道我该如何解决这个问题。
17:39:16.998 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.105 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.224 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.348 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.408 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.479 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.596 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.713 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.838 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.967 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:18.087 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
--------------------------------------------编辑----------------------------
我的shiro ini如下,
[main]
ssl.enabled = false
authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
GoogleRealm = com.hap.Google.GoogleRealm
#GoogleRealm.permissionsLookupEnabled = true
googleCredentialsMatcher = com.hap.Google.GoogleCredentialsMatcher
GoogleRealm.credentialsMatcher = $googleCredentialsMatcher
Ms365Realm = com.hap.MsOffice365.Ms365Realm
#Ms365Realm.permissionsLookupEnabled = true
Ms365CredentialsMatcher = com.hap.MsOffice365.Ms365CredentialsMatcher
Ms365Realm.credentialsMatcher = $Ms365CredentialsMatcher
securityManager.realms = $GoogleRealm,$Ms365Realm
securityManager.rememberMeManager.cipherKey=kPH+bIxk5D2deZiIxcaaaA==
authc.loginUrl = /views/login-oauth.xhtml
[urls]
#Important
/javax.faces.resource/** = anon
/views/login-oauth.xhtml = authc
/views/access-denied.xhtml = anon
/logout = logout
/views/* = authc
/css/* = anon
/errors/* = anon
#I have to punch a hole for the css files
#/** = authc, roles[admin]
整个代码流程基于sample facebook-shiro example
googleRealm 中的 doGetAuthorizationInfo 方法,它实际上从底层数据库 (postgres) 获取角色和权限。
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
AuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
try {
CommonAuthenticationMethods commonAuth = new CommonAuthenticationMethods();
authorizationInfo = commonAuth.doGetAuthorizationInfo(principals);
LOGGER.info("GoogleRealm: doGetAuthorizationInfo is called!!");
} catch (Exception e) {
LOGGER.debug("GoogleRealm : doGetAuthorizationInfo: exception occurred!! " + e.getMessage());
//throw e;
}
return authorizationInfo;
}
像这样添加了 EnvironmentLoaderListener 和 ShiroFilter。正在关注 link
<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>
为什么授权过滤器在这里被调用了这么多次?
------------------------------------编辑------ --------------------------------
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>bintray-deluan-maven</id>
<name>bintray</name>
<url>http://dl.bintray.com/deluan/maven</url>
</repository>
</repositories>
好像在调用shiro:hasAnyRoles
的时候调用了授权方法。以上是我如何在我的 pom.xml 中添加 Deluan 存储库,以便能够在我拥有的 jsf 页面中使用 shiro 标签。我拥有的示例jsf页面之一如下,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:icecore="http://www.icefaces.org/icefaces/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:shiro="http://shiro.apache.org/tags">
<h:head>
<title>Welcome Page</title>
</h:head>
<h:body>
<shiro:hasAnyRoles name="admin,backup-admin,sys-admin">
<h2> Welcome! </h2>
</shiro:hasAnyRoles>
<shiro:hasAnyRoles name="user,admin">
<h2> You too Welcome! </h2>
</shiro:hasAnyRoles>
</h:body>
</html>
这个简单的页面用作欢迎页面,每次刷新它似乎都会调用 doAuthentication 方法 3 次。当然我在这里做错了什么:(我应该看哪里的任何指示?
===========================编辑================= ===========
<!-- Shiro Environment Listener -->
<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>
您似乎忽略了来自 commonAuth.doGetAuthorizationInfo
的错误,这将导致经过身份验证的用户能够访问您的系统。
commonAuth.doGetAuthorizationInfo()
实际上是做什么的?
天呐!我一直在犯一个愚蠢的错误。我已经包含了 Deluan for JSF 的存储库,以便按照一些旧示例为 jsf 配置 taglibs,但没有意识到它已经包含在最新版本的 Shiro 中,因此授权方法被多次调用。当我从依赖项中删除它时,一切都很好。 @Brian Demers,先生,感谢您的宝贵时间和帮助:)
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-faces</artifactId>
<version>2.0</version>
</dependency>
-------------------------------------------- - - - - - - - - - -编辑 - - - - - - - - - - - - - - - ------------------------------
这并没有真正解决问题,错误出现是因为 shiro: 标签本身停止工作。
我遇到这个问题的主要原因是我没有在 securityManager
中配置 cacheManager
。 Shiro 不知道您帐户的授权信息,因为没有缓存。
添加一个cacheManager
,下面的代码使用内存缓存管理器,你可以添加其他的,比如ehcache
,这里是一个使用内存缓存的示例:
@Bean
protected CacheManager cacheManager() {
return new MemoryConstrainedCacheManager();
}
然后加入securityManager
:securityManager.setCacheManager(cacheManager);
我使用 apache shiro 和 google oauth 和 microsoft 365 oauth 编写了一个身份验证和授权模块。它允许用户使用那里的 google/ms 凭据登录没问题,但是授权过滤器被调用了很多次。下面是我从一次登录中获得的调试日志的示例。授权周期被调用了很多次。那么任何人都可以知道我该如何解决这个问题。
17:39:16.998 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.105 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.224 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.348 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.408 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.479 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.596 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.713 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.838 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:17.967 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
17:39:18.087 [qtp670971910-28] INFO com.hap.Google.GoogleRealm - GoogleRealm: doGetAuthorizationInfo is called!!
--------------------------------------------编辑----------------------------
我的shiro ini如下,
[main]
ssl.enabled = false
authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
GoogleRealm = com.hap.Google.GoogleRealm
#GoogleRealm.permissionsLookupEnabled = true
googleCredentialsMatcher = com.hap.Google.GoogleCredentialsMatcher
GoogleRealm.credentialsMatcher = $googleCredentialsMatcher
Ms365Realm = com.hap.MsOffice365.Ms365Realm
#Ms365Realm.permissionsLookupEnabled = true
Ms365CredentialsMatcher = com.hap.MsOffice365.Ms365CredentialsMatcher
Ms365Realm.credentialsMatcher = $Ms365CredentialsMatcher
securityManager.realms = $GoogleRealm,$Ms365Realm
securityManager.rememberMeManager.cipherKey=kPH+bIxk5D2deZiIxcaaaA==
authc.loginUrl = /views/login-oauth.xhtml
[urls]
#Important
/javax.faces.resource/** = anon
/views/login-oauth.xhtml = authc
/views/access-denied.xhtml = anon
/logout = logout
/views/* = authc
/css/* = anon
/errors/* = anon
#I have to punch a hole for the css files
#/** = authc, roles[admin]
整个代码流程基于sample facebook-shiro example googleRealm 中的 doGetAuthorizationInfo 方法,它实际上从底层数据库 (postgres) 获取角色和权限。
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
AuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
try {
CommonAuthenticationMethods commonAuth = new CommonAuthenticationMethods();
authorizationInfo = commonAuth.doGetAuthorizationInfo(principals);
LOGGER.info("GoogleRealm: doGetAuthorizationInfo is called!!");
} catch (Exception e) {
LOGGER.debug("GoogleRealm : doGetAuthorizationInfo: exception occurred!! " + e.getMessage());
//throw e;
}
return authorizationInfo;
}
像这样添加了 EnvironmentLoaderListener 和 ShiroFilter。正在关注 link
<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>
为什么授权过滤器在这里被调用了这么多次?
------------------------------------编辑------ --------------------------------
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>bintray-deluan-maven</id>
<name>bintray</name>
<url>http://dl.bintray.com/deluan/maven</url>
</repository>
</repositories>
好像在调用shiro:hasAnyRoles
的时候调用了授权方法。以上是我如何在我的 pom.xml 中添加 Deluan 存储库,以便能够在我拥有的 jsf 页面中使用 shiro 标签。我拥有的示例jsf页面之一如下,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:icecore="http://www.icefaces.org/icefaces/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:shiro="http://shiro.apache.org/tags">
<h:head>
<title>Welcome Page</title>
</h:head>
<h:body>
<shiro:hasAnyRoles name="admin,backup-admin,sys-admin">
<h2> Welcome! </h2>
</shiro:hasAnyRoles>
<shiro:hasAnyRoles name="user,admin">
<h2> You too Welcome! </h2>
</shiro:hasAnyRoles>
</h:body>
</html>
这个简单的页面用作欢迎页面,每次刷新它似乎都会调用 doAuthentication 方法 3 次。当然我在这里做错了什么:(我应该看哪里的任何指示?
===========================编辑================= ===========
<!-- Shiro Environment Listener -->
<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>
您似乎忽略了来自 commonAuth.doGetAuthorizationInfo
的错误,这将导致经过身份验证的用户能够访问您的系统。
commonAuth.doGetAuthorizationInfo()
实际上是做什么的?
天呐!我一直在犯一个愚蠢的错误。我已经包含了 Deluan for JSF 的存储库,以便按照一些旧示例为 jsf 配置 taglibs,但没有意识到它已经包含在最新版本的 Shiro 中,因此授权方法被多次调用。当我从依赖项中删除它时,一切都很好。 @Brian Demers,先生,感谢您的宝贵时间和帮助:)
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-faces</artifactId>
<version>2.0</version>
</dependency>
-------------------------------------------- - - - - - - - - - -编辑 - - - - - - - - - - - - - - - ------------------------------
这并没有真正解决问题,错误出现是因为 shiro: 标签本身停止工作。
我遇到这个问题的主要原因是我没有在 securityManager
中配置 cacheManager
。 Shiro 不知道您帐户的授权信息,因为没有缓存。
添加一个cacheManager
,下面的代码使用内存缓存管理器,你可以添加其他的,比如ehcache
,这里是一个使用内存缓存的示例:
@Bean
protected CacheManager cacheManager() {
return new MemoryConstrainedCacheManager();
}
然后加入securityManager
:securityManager.setCacheManager(cacheManager);