- 新增AbstractRememberMeManager 实现类
package com.file.system.plugin.shiro;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
/**
* 中危】Apache Shiro rememberMe参数秘钥可被枚举 解决
*
*/
public class IgnoreRememberManager extends AbstractRememberMeManager {
@Override
protected void forgetIdentity(Subject subject) {
}
@Override
protected void rememberSerializedIdentity(Subject subject, byte[] bytes) {
}
@Override
protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {
return new byte[0];
}
@Override
public void forgetIdentity(SubjectContext subjectContext) {
}
}
- ShiroConfig文件中使用@Bean注解方式注入
@Bean(name = "rememberMeManager")
public AbstractRememberMeManager rememberMeManager() {
return new IgnoreRememberManager();
}
- 设置DefaultWebSecurityManager
@Bean
public SecurityManager shiroSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(customRealm());
//配置seesion
securityManager.setSessionManager(sessionManager());
//解决漏洞
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
package com.file.system.plugin.shiro;
import com.file.system.plugin.shiro.filter.ShiroLoginFilter;
import com.file.system.service.ShiroService;
import com.file.system.service.impl.ShiroServiceImpl;
import com.file.system.tools.console.Read;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.AbstractValidatingSessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.servlet.Filter;
import java.security.NoSuchAlgorithmException;
import java.util.*;
@Configuration
public class ShiroConfig {
@Bean
public ShiroService shiroService() {
return new ShiroServiceImpl();
}
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiro = new ShiroFilterFactoryBean();
shiro.setSecurityManager(securityManager);
shiro.setLoginUrl("/login");
shiro.setUnauthorizedUrl("/not/auth");
Map<String, Filter> filterMap = new HashMap<>();
//自定义or角色权限
filterMap.put("roleOrFilter", new RoleOrFilter());
//map里面key值要为authc才能使用自定义的过滤器
filterMap.put("authc", new ShiroLoginFilter());
shiro.setFilters(filterMap);
Map<String, String> chainMap = new LinkedHashMap<>();
chainMap.put("/static/**", "anon");//放开的静态文件目录
chainMap.put("/**", "authc");//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证
shiro.setFilterChainDefinitionMap(chainMap);
Read.console("shiro");
return shiro;
}
/**
* shiro缓存管理器;
* 需要注入对应的其它的实体类中:
* 1、安全管理器:securityManager
* 可见securityManager是整个shiro的核心;
*/
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:shiro/ehcache-shiro.xml");
return cacheManager;
}
@Bean
public SecurityManager shiroSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(customRealm());
//配置seesion
securityManager.setSessionManager(sessionManager());
//记住我
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean(name = "rememberMeManager")
public AbstractRememberMeManager rememberMeManager() {
return new IgnoreRememberManager();
}
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
customRealm.setCachingEnabled(true);
//启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
customRealm.setAuthenticationCachingEnabled(true);
//缓存AuthenticationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置
customRealm.setAuthenticationCacheName("authenticationCache");
//启用授权缓存,即缓存AuthorizationInfo信息,默认false
customRealm.setAuthorizationCachingEnabled(true);
//缓存AuthorizationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置
customRealm.setAuthorizationCacheName("authorizationCache");
return customRealm;
}
/**
* 配置session监听
*/
@Bean("sessionListener")
public ShiroSessionListener sessionListener() {
ShiroSessionListener sessionListener = new ShiroSessionListener();
return sessionListener;
}
/**
* 配置会话ID生成器
*/
@Bean
public SessionIdGenerator sessionIdGenerator() {
return new JavaUuidSessionIdGenerator();
}
/**
* SessionDAO的作用是为Session提供CRUD并进行持久化的一个shiro组件
* MemorySessionDAO 直接在内存中进行会话维护
* EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。
*/
@Bean
public SessionDAO sessionDAO() {
EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
//使用ehCacheManager
enterpriseCacheSessionDAO.setCacheManager(ehCacheManager());
//设置session缓存的名字 默认为 shiro-activeSessionCache
enterpriseCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
//sessionId生成器
enterpriseCacheSessionDAO.setSessionIdGenerator(sessionIdGenerator());
return enterpriseCacheSessionDAO;
}
/**
* shiro session的管理
*/
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(-1000);
//配置session的监听
Collection<SessionListener> listeners = new ArrayList<>();
listeners.add(sessionListener());
sessionManager.setSessionListeners(listeners);
//取消url 后面的 JSESSIONID
sessionManager.setSessionIdUrlRewritingEnabled(false);
SimpleCookie cookie = new SimpleCookie("system.seesion");
cookie.setHttpOnly(true);
cookie.setMaxAge(Integer.MAX_VALUE);
sessionManager.setSessionIdCookie(cookie);
//设置检查seesion时间
sessionManager.setSessionValidationInterval(AbstractValidatingSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL);
//设置在cookie中的sessionId名称
sessionManager.setSessionIdCookie(cookie);
//设置sessionDao对session查询,在查询在线用户service中用到了
sessionManager.setSessionDAO(sessionDAO());
return sessionManager;
}
/**
* 让某个实例的某个方法的返回值注入为Bean的实例
* Spring静态注入
*/
@Bean
public MethodInvokingFactoryBean getMethodInvokingFactoryBean() {
MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
factoryBean.setArguments(new Object[]{shiroSecurityManager()});
return factoryBean;
}
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
// 设置代理类
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
@Bean("authorizationAttributeSourceAdvisor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}