package com.yuanchu.limslaboratory.shiro.config;
|
|
import com.yuanchu.limslaboratory.shiro.filter.JwtFilter;
|
import com.yuanchu.limslaboratory.shiro.MultiRealmAuthenticator;
|
import com.yuanchu.limslaboratory.shiro.realm.JwtRealm;
|
import com.yuanchu.limslaboratory.shiro.realm.ShiroRealm;
|
import com.yuanchu.limslaboratory.shiro.utils.JwtCredentialsMatcher;
|
import org.apache.shiro.authc.credential.CredentialsMatcher;
|
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
import org.apache.shiro.authc.pam.AuthenticationStrategy;
|
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
|
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
|
import org.apache.shiro.authz.Authorizer;
|
import org.apache.shiro.authz.ModularRealmAuthorizer;
|
import org.apache.shiro.crypto.hash.Md5Hash;
|
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
import org.apache.shiro.mgt.SecurityManager;
|
import org.apache.shiro.mgt.SessionStorageEvaluator;
|
import org.apache.shiro.realm.Realm;
|
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.DefaultWebSecurityManager;
|
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Configuration;
|
|
import javax.servlet.Filter;
|
import java.util.*;
|
|
@Configuration
|
public class ShiroConfig {
|
|
/**
|
* 不向 Spring容器中注册 JwtFilter Bean,防止 Spring 将 JwtFilter 注册为全局过滤器
|
* 全局过滤器会对所有请求进行拦截,而本例中只需要拦截除 /login 和 /logout 外的请求
|
* 另一种简单做法是:直接去掉 jwtFilter()上的 @Bean 注解
|
*/
|
@Bean
|
public FilterRegistrationBean<Filter> registration(JwtFilter filter) {
|
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>(filter);
|
registration.setEnabled(false);
|
return registration;
|
}
|
|
//ShiroFilter过滤所有请求
|
@Bean
|
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
|
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
//给ShiroFilter配置安全管理器
|
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
|
// 添加 jwt 专用过滤器,拦截除 /login 和 /logout 外的请求
|
Map<String, Filter> filterMap = new LinkedHashMap<>();
|
filterMap.put("jwtFilter", new JwtFilter());
|
shiroFilterFactoryBean.setFilters(filterMap);
|
|
//配置系统公共资源
|
Map<String, String> map = new HashMap<String, String>();
|
|
// swagger放行
|
map.put("/doc.html", "anon");
|
map.put("/webjars/**/**", "anon");
|
map.put("/swagger-resources", "anon");
|
map.put("/api-docs", "anon");
|
map.put("/v3/**", "anon");
|
|
map.put("/link-basic/*", "anon");
|
map.put("/user/login/**","anon");//表示这个为公共资源 一定是在受限资源上面
|
// map.put("/**","jwtFilter");//表示这个资源需要认证和授权
|
|
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
|
|
return shiroFilterFactoryBean;
|
}
|
|
/**
|
* 配置 ModularRealmAuthenticator
|
*/
|
@Bean
|
public ModularRealmAuthenticator authenticator() {
|
ModularRealmAuthenticator authenticator = new MultiRealmAuthenticator();
|
// 设置多 Realm的认证策略,默认 AtLeastOneSuccessfulStrategy
|
AuthenticationStrategy strategy = new FirstSuccessfulStrategy();
|
authenticator.setAuthenticationStrategy(strategy);
|
return authenticator;
|
}
|
|
|
/**
|
* 禁用session, 不保存用户登录状态。保证每次请求都重新认证
|
*/
|
@Bean
|
protected SessionStorageEvaluator sessionStorageEvaluator() {
|
DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
|
sessionStorageEvaluator.setSessionStorageEnabled(false);
|
return sessionStorageEvaluator;
|
}
|
|
/**
|
* 配置 SecurityManager:权限管理器
|
*/
|
@Bean
|
public DefaultWebSecurityManager securityManager() {
|
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
|
// 1.身份验证器
|
securityManager.setAuthenticator(authenticator());
|
|
// 2.管理Realm
|
List<Realm> realms = new ArrayList<Realm>(16);
|
realms.add(JwtRealm());
|
realms.add(shiroRealm());
|
securityManager.setRealms(realms); // 配置多个realm
|
|
// 3.关闭shiro自带的session
|
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
|
subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
|
securityManager.setSubjectDAO(subjectDAO);
|
|
return securityManager;
|
}
|
|
// 创建自定义Realm
|
@Bean
|
public Realm shiroRealm() {
|
ShiroRealm realm = new ShiroRealm();
|
// HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
|
//// //设置使用MD5加密算法
|
//// credentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
|
//// //散列次数
|
//// credentialsMatcher.setHashIterations(1024);
|
// realm.setCredentialsMatcher(credentialsMatcher);
|
return realm;
|
}
|
|
@Bean
|
public Realm JwtRealm(){
|
JwtRealm jwtRealm = new JwtRealm();
|
// 设置加密算法
|
CredentialsMatcher credentialsMatcher = new JwtCredentialsMatcher();
|
// 设置加密次数
|
jwtRealm.setCredentialsMatcher(credentialsMatcher);
|
return jwtRealm;
|
}
|
|
|
// 以下三中bean通用,固定配置
|
|
/**
|
* 交由 Spring 来自动地管理 Shiro-Bean 的生命周期
|
*/
|
@Bean
|
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
|
return new LifecycleBeanPostProcessor();
|
}
|
|
/**
|
* 为 Spring-Bean 开启对 Shiro 注解的支持
|
*/
|
@Bean
|
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
|
return authorizationAttributeSourceAdvisor;
|
}
|
|
/**
|
* 开启AOP方法级权限检查
|
*/
|
@Bean
|
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
|
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
advisorAutoProxyCreator.setProxyTargetClass(true);
|
return advisorAutoProxyCreator;
|
}
|
}
|