JSF 2 + Spring 3 + Shiro - Session Timeout doesn&#

2019-07-25 13:59发布

I have this JSF 2.0/Spring app that added Apache Shiro to and a redirect after session timeout never occurs when a user clicks on a command button or triggers an AJAX request. It does work when they refresh the browser. This is happening in all browsers. Here's my applicationContext.xml:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/index.faces"/>
        <property name="filterChainDefinitions">
                <value>
                        /* = authc 
                </value>
        </property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="opacsRealm" />
</bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<bean id="sha512Matcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">

        <property name="hashAlgorithmName" value="SHA-256" />
        <property name="hashIterations" value="1024" />
</bean>



<bean id="opacsRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
        <property name="dataSource" ref="dataSource" />
        <property name="authenticationQuery" 
                value="select PASSWORD, SALT from SEC_USERS where NAME = ?" />
        <property name="userRolesQuery" 
                value="SELECT ROLE_NAME FROM SEC_USERS_ROLES WHERE USER_NAME = ?" />
        <property name="permissionsQuery" 
                value="SELECT permission FROM SEC_ROLES_PERMISSIONS WHERE ROLE_NAME = ?" />
        <property name="permissionsLookupEnabled" value="true" />
        <property name="saltStyle" value="COLUMN" />
        <property name="credentialsMatcher" ref="sha512Matcher"/>
</bean>

Am I doing something wrong in the setup? The web.xml looks like this:

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
  <!-- web.xml expects the session timeout in minutes: -->
  <session-timeout>1</session-timeout>
</session-config>

1条回答
趁早两清
2楼-- · 2019-07-25 14:30

Just replied to your mail. What is happening is that the redirect is handled seamlessly by the browser in your Ajax call so Shiro does redirect to the login page and the end result of your Ajax request is the HTML content of the login page, which isn't really what you want!

The gist of how to work around this is to add a (custom) Shiro filter to your Ajax Api urls that checks the Subject for being authenticated and instead of redirecting to login return a response that your Ajax request understands to indicate that the user is not logged in. Client side handling of this response can then do a redirect to the login page (or perhaps the same page because Shiro will then redirect to login but can be configured to remember where you were trying to go and hence take the user back to the correct page upon successful login).

My filter implementation returns Http code 401 along with "WWW-Authentication" header and a custom "challenge scheme" (if you did a basic authentication challenge then the browser would pop up its basic authentication dialog - there is already a Shiro filter that does this).

In your Ajax call you need to detect this response, currently I have a clunky error callback that does it BUT I think it should be possible to modify the JavaScript library (JQuery, whatever) to handle this seamlessly.

查看更多
登录 后发表回答