当会话超时时,我需要将我的webapp(Java + angular)重定向到登录页面。 shiro是自动进行重定向还是由代码处理?
我尝试了几次黑客攻击,但对我来说并不起作用。 我尝试将会话超时添加到我的web.xml,但它根本没有生效。 我尝试更新我的shiro.ini,但随后又无法登录我的应用程序了!
您能否帮助找出这些文件中的错误或建议在这种情况下应该做些什么。
提前致谢。
的web.xml:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ResourceManager</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- session-config>
<session-timeout>1</session-timeout>
</session-config>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/Login.html</location>
</error-page-->
<listener>
<listener-class>
com.<our customized package>.logging.AppLifeCircleListener
</listener-class>
</listener>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>shiro-filter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiro-filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>login</servlet-name>
<jsp-file>/Login.jsp</jsp-file>
</servlet>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/management/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/privilege/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/file-explorer/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/Login.html</url-pattern>
</servlet-mapping>
</web-app>
&#13;
shiro.ini:
[main]
# LDAP Settinng
contextFactory = com.ibm.datafabrication.web.server.security.JndiLdapContextFactoryExt
contextFactory.url = ldap://<host>:389
contextFactory.systemUsername = <...>
contextFactory.keyPath = <>
contextFactory.encodedSystemPassword = ...
ldapRealm = com.<>.ActiveDirectoryRealm
ldapRealm.ldapContextFactory = $contextFactory
ldapRealm.userSearchFilter = (sAMAccountName={0})
ldapRealm.groupNameAttribute = cn
ldapRealm.searchBase = DC=<...>,DC=<...>,DC=com
ldapRealm.groupRolesMap = dfp_users:user,dfp_admins:admin
# SQLite Setting
ds = org.sqlite.SQLiteDataSource
ds.url = jdbc:sqlite:<>.db
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $ds
jdbcRealm.permissionsLookupEnabled = false
jdbcRealm.authenticationQuery = SELECT Password FROM Users WHERE Name=?
jdbcRealm.userRolesQuery = WITH uname(name) AS (VALUES(?)) SELECT 'user' FROM Users, uname WHERE Users.Name=uname.name UNION ALL SELECT 'admin' FROM (SELECT Id FROM Users, uname WHERE Users.Name=uname.name) LEFT JOIN Admins on Id = Admins.UserId WHERE UserId NOT NULL
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
credentialsMatcher.storedCredentialsHexEncoded = true
jdbcRealm.credentialsMatcher = $credentialsMatcher
authc.loginUrl = /Login.html
securityManager.realms = $jdbcRealm
authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
>>>>>>>>>>>>>>>>>>>>> What I tired
# session timeout
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionMode=native
securityManager.sessionManager.globalSessionTimeout = 60000
securityManager.sessionManager = $sessionManager
sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
sessionValidationScheduler.interval = 30000
securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[urls]
/logout = logout
/css/** = anon
/images/** = anon
/plugins/** = anon
/favicon.ico = anon
/tdf.ico = anon
/Login.html = authc
...
/** = authc, roles[user]
&#13;
答案 0 :(得分:0)
您可以保留web.xml
原样,因为Shiro与此文件中的配置无关。您的servlet的HttpSession
和Shiro HttpServletRequest
使用的Session
存在差异。它们是完全不同的东西。所以不要被servlet的会话配置和Shiro的会话配置搞糊涂了。在这种情况下,我们让Shiro处理您的会话。
shiro.ini的问题
您正在覆盖您要写入DefaultWebSessionManager
的设置:
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager // Define a sessionManager variable
securityManager.sessionMode=native
securityManager.sessionManager.globalSessionTimeout = 60000 // set a securityManager.sessionManager property
securityManager.sessionManager = $sessionManager // override the property by setting the object
您必须先设置对象:
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
securityManager.sessionMode=native
securityManager.sessionManager.globalSessionTimeout = 60000
您不需要ExecutorServiceSessionValidationScheduler
,因为DefaultWebSessionManager
已经提供了一个valdiator。一个工作示例可能如下所示:
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
# Session timeout token_ttl_ms = 14 days
sessionManager.globalSessionTimeout = 1209600000
# Session valdiation = 15 minutes
sessionManager.sessionValidationInterval = 900000
securityManager = org.apache.shiro.web.mgt.DefaultWebSecurityManager
securityManager.sessionManager = $sessionManager
<强> DefaultWebSessionManager 强>
DefaultWebSessionManager提供您正在寻找的所有功能(基本上)。当会话在其super上的DefaultWebSessionManager
次呼叫onExpiration
到期时,会通知其所有听众关于SessionManager中的到期日期。您只需向SessionManager
注册SessionListener,然后按其onExpiration
方式触发重新加载或重定向即可。也许这种方法非常适合jsp / jspx应用程序
无论如何,请阅读如何在官方文档中注册会话监听器here。
替代方法
另一种方法可能是让您的客户端管理会话状态,并通过调用您的服务让它持续检查到期时间。这可以通过计时器或JavaScript中的循环来完成。
注意强>
org.apache.shiro.authc.credential.Sha256CredentialsMatcher
自2010年起被弃用。
直接使用HashedCredentialsMatcher并设置其hashAlgorithmName属性。
答案 1 :(得分:0)
最后,我使用@ ng-idle / core angular package在我的客户端实现了一个超时解决方案:
https://www.npmjs.com/package/@ng-idle/core
https://hackedbychinese.github.io/ng2-idle/
我还使用@ ng-idle / keepalive连续ping服务器并保持活着:
handleIdle(){
// sets an idle timeout of x seconds, for testing purposes.
this.idle.setIdle(/*Config.SESSION_IDLE*/ this.sessionIdle);
// sets a timeout period of y seconds. after x+y seconds of inactivity, the user will be considered timed out.
this.idle.setTimeout(/*Config.SESSION_TIMEOUT*/ this.sessionTimeout);
// sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
this.idle.onIdleEnd.subscribe(() => this.idleState = 'No longer idle.');
this.idle.onTimeout.subscribe(() => {
this.idleState = 'Timed out!';
this.timedOut = true;
});
this.idle.onIdleStart.subscribe(() => {
this.idleState = 'You\'ve gone idle!'
this.idleModal.open();
}
);
this.idle.onTimeoutWarning.subscribe((countdown) => {
this.idleState = 'You\'ve gone idle! Your session will be timed out in ' + countdown + ' seconds!';
if (countdown == 1){
window.location.href = "../logout";
}
});
// sets the ping interval to z seconds
this.keepalive.interval(/*Config.KEEP_ALIVE_INTERVAL*/this.keepAliveInterval);
this.keepalive.onPing.subscribe(() => {
this.lastPing = new Date();
this.resourcesService.ping();
});
this.reset(); }