3

JavaEE6プロジェクトを作成しましたが、現在、認証と承認にShiroを使用しています。この記事を参考にして(CDIインターセプターを介した承認にShiroを使用してから、Arquillianで簡単にテストする)、ShiroをCDIと統合しました。Subject.getPrincipalがnullの場合を除いて、すべて正常に動作します。

さらに、調査によると、少なくとも2つのSubject.getSession()。getId()がある場合があります。

問題が発生する方法:

  1. ログイン->sessionAでOK
  2. 保護されているリンクをクリックします(pageA)-> ok
  3. 失敗したレコードをデータベースに挿入しようとしました
  4. 同じセキュリティで保護されたリンク(pageA)をクリックします->失敗しました。トレースを見ると、異なるセッションIDsessionBが生成されました。
  5. ページ(pageA)に問題がなくなるまで、更新して更新します。ログインsessionA中に同じセッションIDを取得しました。

何が間違っている可能性がありますか?

私のshiro.iniファイル

[main]
saltedJdbcRealm=com.sido.commons.web.security.shiro.JdbcRealmImpl

# any object property is automatically configurable in Shiro.ini file
saltedJdbcRealm.jndiDataSourceName=Portal 

# the realm should handle also authorization
saltedJdbcRealm.permissionsLookupEnabled=true

# If not filled, subclasses of JdbcRealm assume "select password from users where username = ?"
# first result column is password, second result column is salt 
saltedJdbcRealm.authenticationQuery = SELECT password, salt FROM users WHERE username = ?

# If not filled, subclasses of JdbcRealm assume "select role_name from user_roles where username = ?"
saltedJdbcRealm.userRolesQuery = SELECT name FROM roles a INNER JOIN user_roles b ON a.id=b.role_id INNER JOIN users c ON c.id=b.user_id WHERE c.username = ?

# If not filled, subclasses of JdbcRealm assume "select permission from roles_permissions where role_name = ?"
saltedJdbcRealm.permissionsQuery = SELECT action FROM permissions WHERE role = ?

# password hashing specification, put something big for hasIterations
sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
sha256Matcher.hashAlgorithmName=SHA-256
sha256Matcher.hashIterations=1
saltedJdbcRealm.credentialsMatcher = $sha256Matcher

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO 

cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager 
cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml
securityManager.cacheManager=$cacheManager 

shiro.loginUrl = /login.xhtml

[urls]
/login.xhtml = authc
/logout = logout

web.xml

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Production</param-value>
</context-param>

<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>south-street</param-value>
</context-param>

<!-- Welcome page -->
<welcome-file-list>
    <welcome-file>home.xhtml</welcome-file>
</welcome-file-list>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Map these files with JSF -->
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

SecurityProducer、セキュリティマネージャーをインスタンス化するシングルトンBean。それは利用可能であり、アプリケーション全体に固有である必要がありますか?

@Singleton
public class SecurityProducer {
    @Inject
    private Logger log;
    private SecurityManager securityManager;

    @PostConstruct
    public void init() {
        final String iniFile = "classpath:shiro.ini";
        log.debug("Initializing Shiro INI SecurityManager using " + iniFile);
        securityManager = new IniSecurityManagerFactory(iniFile).getInstance();
        SecurityUtils.setSecurityManager(securityManager);
    }
    ..
}

初期化時にSecurityManagerまたはSubject(シングルトンBean)をバインドしても、問題は修正されません。

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

ありがとう、
czetsuya

4

2 に答える 2

1

ここでweb.xmlベースを構成することで、断続的なセッションの問題を解決したと思います:http ://shiro.apache.org/web.html 。

現在の外観は次のとおりです。http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd "version =" 3.0 ">

<!-- Welcome page -->
<welcome-file-list>
    <welcome-file>home.xhtml</welcome-file>
</welcome-file-list>
<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>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<!-- Map these files with JSF -->
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

しかし、それは本当に解決策ですか?何か案は?

于 2012-11-02T03:11:52.447 に答える
0

サブジェクトを手動でビルドする場合は、それをスレッド呼び出しにバインドする必要があります ThreadContext.bind(subject)。これを行わないと、次の呼び出しSecurityUtils.getSubject()で、以前に作成したものではなく、新しいサブジェクトが返されます。

たとえば、私のアプリケーションでは、リクエストでセッションIDを受け取り、そこからサブジェクトを作成しました。

Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();
ThreadContext.bind(subject);
于 2012-10-31T09:07:40.533 に答える