diff --git a/pom.xml b/pom.xml index 20f6855cb..77489898a 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,12 @@ slf4j-api + + + org.projectlombok + lombok + provided + diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index a1acec922..c882b557e 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -112,6 +112,18 @@ shiro: dbSyncPeriod: 1 # 相隔多久检查一次session的有效性,默认就是10分钟 validationInterval: 10 + anon: + - /favicon.ico** + - /ruoyi.png** + - /css/** + - /docs/** + - /fonts/** + - /img/** + - /ajax/** + - /js/** + - /ruoyi/** + - /druid/** + - /captcha/captchaImage** # 防止XSS攻击 xss: diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 06394c2b6..f54014551 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -17,6 +17,13 @@ + + + org.springframework.boot + spring-boot-configuration-processor + true + + org.springframework.boot diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java index 33228e431..09589bf13 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java @@ -1,21 +1,8 @@ package com.ruoyi.framework.config; -import java.util.LinkedHashMap; -import java.util.Map; -import javax.servlet.Filter; -import org.apache.shiro.cache.ehcache.EhCacheManager; -import org.apache.shiro.codec.Base64; -import org.apache.shiro.mgt.SecurityManager; -import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; -import org.apache.shiro.spring.web.ShiroFilterFactoryBean; -import org.apache.shiro.web.mgt.CookieRememberMeManager; -import org.apache.shiro.web.mgt.DefaultWebSecurityManager; -import org.apache.shiro.web.servlet.SimpleCookie; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.configuration.ShiroProperties; import com.ruoyi.framework.shiro.realm.UserRealm; import com.ruoyi.framework.shiro.session.OnlineSessionDAO; import com.ruoyi.framework.shiro.session.OnlineSessionFactory; @@ -25,7 +12,23 @@ import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter; import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter; import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager; import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler; -import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; +import org.apache.shiro.cache.ehcache.EhCacheManager; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.CookieRememberMeManager; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * 权限配置加载 @@ -37,45 +40,8 @@ public class ShiroConfig { public static final String PREMISSION_STRING = "perms[\"{0}\"]"; - // Session超时时间,单位为毫秒(默认30分钟) - @Value("${shiro.session.expireTime}") - private int expireTime; - - // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟 - @Value("${shiro.session.validationInterval}") - private int validationInterval; - - // 验证码开关 - @Value("${shiro.user.captchaEnabled}") - private boolean captchaEnabled; - - // 验证码类型 - @Value("${shiro.user.captchaType}") - private String captchaType; - - // 设置Cookie的域名 - @Value("${shiro.cookie.domain}") - private String domain; - - // 设置cookie的有效访问路径 - @Value("${shiro.cookie.path}") - private String path; - - // 设置HttpOnly属性 - @Value("${shiro.cookie.httpOnly}") - private boolean httpOnly; - - // 设置Cookie的过期时间,秒为单位 - @Value("${shiro.cookie.maxAge}") - private int maxAge; - - // 登录地址 - @Value("${shiro.user.loginUrl}") - private String loginUrl; - - // 权限认证失败地址 - @Value("${shiro.user.unauthorizedUrl}") - private String unauthorizedUrl; + @Autowired + private ShiroProperties shiroProperties; /** * 缓存管理器 使用Ehcache实现 @@ -136,7 +102,7 @@ public class ShiroConfig { SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler(); // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟 - sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000); + sessionValidationScheduler.setSessionValidationInterval(shiroProperties.getSession().getValidationInterval() * 60 * 1000); // 设置会话验证调度器进行会话验证时的会话管理器 sessionValidationScheduler.setSessionManager(sessionValidationManager()); return sessionValidationScheduler; @@ -154,7 +120,7 @@ public class ShiroConfig // 删除过期的session manager.setDeleteInvalidSessions(true); // 设置全局session超时时间 - manager.setGlobalSessionTimeout(expireTime * 60 * 1000); + manager.setGlobalSessionTimeout(shiroProperties.getSession().getExpireTime() * 60 * 1000); // 去掉 JSESSIONID manager.setSessionIdUrlRewritingEnabled(false); // 是否定时检查session @@ -178,7 +144,7 @@ public class ShiroConfig // 删除过期的session manager.setDeleteInvalidSessions(true); // 设置全局session超时时间 - manager.setGlobalSessionTimeout(expireTime * 60 * 1000); + manager.setGlobalSessionTimeout(shiroProperties.getSession().getExpireTime() * 60 * 1000); // 去掉 JSESSIONID manager.setSessionIdUrlRewritingEnabled(false); // 定义要使用的无效的Session定时调度器 @@ -216,7 +182,7 @@ public class ShiroConfig public LogoutFilter logoutFilter() { LogoutFilter logoutFilter = new LogoutFilter(); - logoutFilter.setLoginUrl(loginUrl); + logoutFilter.setLoginUrl(shiroProperties.getUser().getLoginUrl()); return logoutFilter; } @@ -226,27 +192,34 @@ public class ShiroConfig @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // Shiro的核心安全接口,这个属性是必须的 shiroFilterFactoryBean.setSecurityManager(securityManager); // 身份认证失败,则跳转到登录页面的配置 - shiroFilterFactoryBean.setLoginUrl(loginUrl); + shiroFilterFactoryBean.setLoginUrl(shiroProperties.getUser().getLoginUrl()); // 权限认证失败,则跳转到指定页面 - shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl); + shiroFilterFactoryBean.setUnauthorizedUrl(shiroProperties.getUser().getUnauthorizedUrl()); // Shiro连接约束配置,即过滤链的定义 LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); // 对静态资源设置匿名访问 - filterChainDefinitionMap.put("/favicon.ico**", "anon"); - filterChainDefinitionMap.put("/ruoyi.png**", "anon"); - filterChainDefinitionMap.put("/css/**", "anon"); - filterChainDefinitionMap.put("/docs/**", "anon"); - filterChainDefinitionMap.put("/fonts/**", "anon"); - filterChainDefinitionMap.put("/img/**", "anon"); - filterChainDefinitionMap.put("/ajax/**", "anon"); - filterChainDefinitionMap.put("/js/**", "anon"); - filterChainDefinitionMap.put("/ruoyi/**", "anon"); - filterChainDefinitionMap.put("/druid/**", "anon"); - filterChainDefinitionMap.put("/captcha/captchaImage**", "anon"); +// filterChainDefinitionMap.put("/favicon.ico**", "anon"); +// filterChainDefinitionMap.put("/ruoyi.png**", "anon"); +// filterChainDefinitionMap.put("/css/**", "anon"); +// filterChainDefinitionMap.put("/docs/**", "anon"); +// filterChainDefinitionMap.put("/fonts/**", "anon"); +// filterChainDefinitionMap.put("/img/**", "anon"); +// filterChainDefinitionMap.put("/ajax/**", "anon"); +// filterChainDefinitionMap.put("/js/**", "anon"); +// filterChainDefinitionMap.put("/ruoyi/**", "anon"); +// filterChainDefinitionMap.put("/druid/**", "anon"); +// filterChainDefinitionMap.put("/captcha/captchaImage**", "anon"); + + List anonList=shiroProperties.getAnon(); + for(String anonUrl:anonList){ + filterChainDefinitionMap.put(anonUrl, "anon"); + } + // 退出 logout地址,shiro去清除session filterChainDefinitionMap.put("/logout", "logout"); // 不需要拦截的访问 @@ -276,7 +249,7 @@ public class ShiroConfig public OnlineSessionFilter onlineSessionFilter() { OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter(); - onlineSessionFilter.setLoginUrl(loginUrl); + onlineSessionFilter.setLoginUrl(shiroProperties.getUser().getLoginUrl()); return onlineSessionFilter; } @@ -297,8 +270,8 @@ public class ShiroConfig public CaptchaValidateFilter captchaValidateFilter() { CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter(); - captchaValidateFilter.setCaptchaEnabled(captchaEnabled); - captchaValidateFilter.setCaptchaType(captchaType); + captchaValidateFilter.setCaptchaEnabled(shiroProperties.getUser().isCaptchaEnabled()); + captchaValidateFilter.setCaptchaType(shiroProperties.getUser().getCaptchaType()); return captchaValidateFilter; } @@ -308,10 +281,10 @@ public class ShiroConfig public SimpleCookie rememberMeCookie() { SimpleCookie cookie = new SimpleCookie("rememberMe"); - cookie.setDomain(domain); - cookie.setPath(path); - cookie.setHttpOnly(httpOnly); - cookie.setMaxAge(maxAge * 24 * 60 * 60); + cookie.setDomain(shiroProperties.getCookie().getDomain()); + cookie.setPath(shiroProperties.getCookie().getPath()); + cookie.setHttpOnly(shiroProperties.getCookie().isHttpOnly()); + cookie.setMaxAge(shiroProperties.getCookie().getMaxAge() * 24 * 60 * 60); return cookie; } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/configuration/ShiroProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/configuration/ShiroProperties.java new file mode 100644 index 000000000..46b1afeb0 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/configuration/ShiroProperties.java @@ -0,0 +1,76 @@ +package com.ruoyi.framework.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author Charles + * @date 2018/11/13 + * @desciption + */ +@Data +@Component +@ConfigurationProperties(prefix = "shiro") +public class ShiroProperties { + + private User user; + + private Cookie cookie; + + private Session session; + + private List anon; + + + @Data + public static class User{ + // 登录地址 + private String loginUrl; + + // 权限认证失败地址 + private String unauthorizedUrl; + + // 首页地址 + private String indexUrl; + + // 验证码开关 + private boolean captchaEnabled; + + // 验证码类型 math 数组计算 char 字符 + private String captchaType; + + } + + @Data + public static class Cookie{ + + // 设置Cookie的域名 默认空,即当前访问的域名 + private String domain; + + // 设置cookie的有效访问路径 + private String path; + + // 设置HttpOnly属性 + private boolean httpOnly; + + // 设置Cookie的过期时间,天为单位 + private int maxAge; + } + + @Data + public static class Session { + // Session超时时间(默认30分钟) + private int expireTime; + + // 同步session到数据库的周期(默认1分钟) + private int dbSyncPeriod; + + // 相隔多久检查一次session的有效性,默认就是10分钟 + private int validationInterval; + } + + +} \ No newline at end of file