|
@@ -16,6 +16,7 @@ import org.apache.shiro.mgt.SecurityManager;
|
|
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
|
|
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
|
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
|
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
|
|
|
|
+import org.apache.shiro.web.servlet.Cookie;
|
|
|
import org.apache.shiro.web.servlet.SimpleCookie;
|
|
import org.apache.shiro.web.servlet.SimpleCookie;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
@@ -28,6 +29,7 @@ import com.ruoyi.common.utils.spring.SpringUtils;
|
|
|
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
|
|
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
|
|
|
import com.ruoyi.framework.shiro.realm.UserRealm;
|
|
import com.ruoyi.framework.shiro.realm.UserRealm;
|
|
|
import com.ruoyi.framework.shiro.rememberMe.CustomCookieRememberMeManager;
|
|
import com.ruoyi.framework.shiro.rememberMe.CustomCookieRememberMeManager;
|
|
|
|
|
+import com.ruoyi.framework.shiro.web.filter.embed.EmbedAwareUserFilter;
|
|
|
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
|
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
|
|
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
|
|
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
|
|
|
import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
|
|
import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
|
|
@@ -222,8 +224,16 @@ public class ShiroConfig
|
|
|
manager.setDeleteInvalidSessions(true);
|
|
manager.setDeleteInvalidSessions(true);
|
|
|
// 设置全局session超时时间
|
|
// 设置全局session超时时间
|
|
|
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
|
|
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
|
|
|
- // 去掉 JSESSIONID
|
|
|
|
|
|
|
+ // 去掉 URL 重写 ;JSESSIONID=(仍使用 Cookie 传递会话)
|
|
|
manager.setSessionIdUrlRewritingEnabled(false);
|
|
manager.setSessionIdUrlRewritingEnabled(false);
|
|
|
|
|
+ // 显式会话 Cookie:host-only + SameSite=Lax,保证同主机:8899 iframe 登录后能带到工作台
|
|
|
|
|
+ SimpleCookie sessionIdCookie = new SimpleCookie("JSESSIONID");
|
|
|
|
|
+ sessionIdCookie.setHttpOnly(true);
|
|
|
|
|
+ sessionIdCookie.setPath(StringUtils.isNotEmpty(path) ? path : "/");
|
|
|
|
|
+ // 不设置 Domain → host-only;避免 yml/反代写成上游 IP 导致浏览器拒收
|
|
|
|
|
+ sessionIdCookie.setSameSite(Cookie.SameSiteOptions.LAX);
|
|
|
|
|
+ manager.setSessionIdCookie(sessionIdCookie);
|
|
|
|
|
+ manager.setSessionIdCookieEnabled(true);
|
|
|
// 定义要使用的无效的Session定时调度器
|
|
// 定义要使用的无效的Session定时调度器
|
|
|
manager.setSessionValidationScheduler(SpringUtils.getBean(SpringSessionValidationScheduler.class));
|
|
manager.setSessionValidationScheduler(SpringUtils.getBean(SpringSessionValidationScheduler.class));
|
|
|
// 是否定时检查session
|
|
// 是否定时检查session
|
|
@@ -314,6 +324,8 @@ public class ShiroConfig
|
|
|
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
|
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
|
|
|
|
|
|
|
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
|
|
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
|
|
|
|
|
+ // 替换默认 user:未登录踢回时保留 embed=1
|
|
|
|
|
+ filters.put("user", embedAwareUserFilter());
|
|
|
filters.put("onlineSession", onlineSessionFilter());
|
|
filters.put("onlineSession", onlineSessionFilter());
|
|
|
filters.put("syncOnlineSession", syncOnlineSessionFilter());
|
|
filters.put("syncOnlineSession", syncOnlineSessionFilter());
|
|
|
filters.put("captchaValidate", captchaValidateFilter());
|
|
filters.put("captchaValidate", captchaValidateFilter());
|
|
@@ -367,10 +379,15 @@ public class ShiroConfig
|
|
|
public SimpleCookie rememberMeCookie()
|
|
public SimpleCookie rememberMeCookie()
|
|
|
{
|
|
{
|
|
|
SimpleCookie cookie = new SimpleCookie("rememberMe");
|
|
SimpleCookie cookie = new SimpleCookie("rememberMe");
|
|
|
- cookie.setDomain(domain);
|
|
|
|
|
|
|
+ // Domain 为空时不要 setDomain,保持 host-only(与会话 Cookie 一致)
|
|
|
|
|
+ if (StringUtils.isNotEmpty(domain))
|
|
|
|
|
+ {
|
|
|
|
|
+ cookie.setDomain(domain);
|
|
|
|
|
+ }
|
|
|
cookie.setPath(path);
|
|
cookie.setPath(path);
|
|
|
cookie.setHttpOnly(httpOnly);
|
|
cookie.setHttpOnly(httpOnly);
|
|
|
cookie.setMaxAge(maxAge * 24 * 60 * 60);
|
|
cookie.setMaxAge(maxAge * 24 * 60 * 60);
|
|
|
|
|
+ cookie.setSameSite(Cookie.SameSiteOptions.LAX);
|
|
|
return cookie;
|
|
return cookie;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -404,11 +421,21 @@ public class ShiroConfig
|
|
|
kickoutSessionFilter.setMaxSession(maxSession);
|
|
kickoutSessionFilter.setMaxSession(maxSession);
|
|
|
// 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序
|
|
// 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序
|
|
|
kickoutSessionFilter.setKickoutAfter(kickoutAfter);
|
|
kickoutSessionFilter.setKickoutAfter(kickoutAfter);
|
|
|
- // 被踢出后重定向到的地址;
|
|
|
|
|
|
|
+ // 被踢出后重定向到的地址(不带 embed,避免影响线上主流登录页;iframe 内由 login.html 自动补 embed=1)
|
|
|
kickoutSessionFilter.setKickoutUrl("/login?kickout=1");
|
|
kickoutSessionFilter.setKickoutUrl("/login?kickout=1");
|
|
|
return kickoutSessionFilter;
|
|
return kickoutSessionFilter;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 未登录跳转:保留 HIS iframe embed 参数
|
|
|
|
|
+ */
|
|
|
|
|
+ public EmbedAwareUserFilter embedAwareUserFilter()
|
|
|
|
|
+ {
|
|
|
|
|
+ EmbedAwareUserFilter filter = new EmbedAwareUserFilter();
|
|
|
|
|
+ filter.setLoginUrl(loginUrl);
|
|
|
|
|
+ return filter;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* thymeleaf模板引擎和shiro框架的整合
|
|
* thymeleaf模板引擎和shiro框架的整合
|
|
|
*/
|
|
*/
|