com.github.kaizen4j.shiro.ShiroAutoConfiguration Maven / Gradle / Ivy
package com.github.kaizen4j.shiro;
import com.github.kaizen4j.redis.RedisAutoConfiguration;
import com.github.kaizen4j.shiro.cache.ShiroRedisCacheManager;
import com.github.kaizen4j.shiro.captcha.CaptchaStore;
import com.github.kaizen4j.shiro.captcha.DefaultCaptchaManager;
import com.github.kaizen4j.shiro.captcha.JCaptchaFilter;
import com.github.kaizen4j.shiro.captcha.RedisCaptchaStore;
import com.github.kaizen4j.shiro.csrf.CsrfFilter;
import com.github.kaizen4j.shiro.realm.SimpleJdbcRealm;
import com.github.kaizen4j.shiro.session.RedisSessionDAO;
import javax.sql.DataSource;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.jdbc.JdbcRealm.SaltStyle;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
/**
* @author liuguowen
*/
@Configuration
@ComponentScan(basePackages = {"com.github.kaizen4j.shiro"})
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class ShiroAutoConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ShiroAutoConfiguration.class);
@Value("#{ @environment['shiro.hashedCredentialsMatcher.hashAlgorithmName'] ?: T(org.apache.shiro.crypto.hash.Md5Hash).ALGORITHM_NAME }")
private String hashAlgorithmName;
@Value("${shiro.hashedCredentialsMatcher.hashIterations:3}")
private int hashIterations;
@Value("#{ @environment['shiro.cacheManager.expireMillis'] ?: T(com.github.kaizen4j.shiro.cache.ShiroRedisCacheManager).DEFAULT_CACHE_EXPIRE_MILLIS }")
private long cacheExpireMillis;
@Value("${spring.application.name}")
private String appName;
@Bean
public HashedCredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);
credentialsMatcher.setHashIterations(hashIterations);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
@Bean
public Realm realm(DataSource dataSource, CredentialsMatcher credentialsMatcher) {
JdbcRealm jdbcRealm = new SimpleJdbcRealm();
jdbcRealm.setDataSource(dataSource);
jdbcRealm.setSaltStyle(SaltStyle.COLUMN);
jdbcRealm.setPermissionsLookupEnabled(true);
jdbcRealm.setCredentialsMatcher(credentialsMatcher);
// 开启权限缓存
jdbcRealm.setAuthorizationCachingEnabled(true);
// 开启认证缓存
jdbcRealm.setAuthenticationCachingEnabled(true);
return jdbcRealm;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// 将 usePrefix 和 proxyTargetClass 二者任意一值设为 true 都可以解决无法映射请求的问题:
// userPrefix 属性设为 true,阻止了 DefaultAdvisorAutoProxyCreator 代理创建行为。
// proxyTargetClass 为 true,使类对象在被二次代理时,仍旧能够找到原始类对象,并且被成功放入映射注册表。
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public CacheManager shiroRedisCacheManager(RedisTemplate redisTemplate) {
// 只用于缓存权限 Authorization 及认证 Authentication 信息。
return new ShiroRedisCacheManager(redisTemplate, appName, cacheExpireMillis);
}
@Bean
public SessionDAO sessionDAO(RedisTemplate redisTemplate) {
// 必须在属性文件中开启 shiro.userNativeSessionManager 值为 true。
// 有单独的缓存过期时间,默认为 session 的过期时间。
return new RedisSessionDAO(redisTemplate);
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition shiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
shiroFilterChainDefinition.addPathDefinition("/**", "anon, csrf");
return shiroFilterChainDefinition;
}
@Bean(name = "csrf")
@ConditionalOnMissingBean(name = "csrf")
public CsrfFilter csrfFilter() {
return new CsrfFilter();
}
@Bean
@ConditionalOnMissingBean
public DefaultCaptchaManager captchaManager(CaptchaStore captchaStore) {
return new DefaultCaptchaManager(captchaStore);
}
@Bean
@ConditionalOnMissingBean
public CaptchaStore captchaStore(RedisTemplate redisTemplate) {
return new RedisCaptchaStore(redisTemplate);
}
@Bean
@ConditionalOnMissingBean
public FilterRegistrationBean jCaptchaFilter(DefaultCaptchaManager captchaManager) {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new JCaptchaFilter(captchaManager));
registration.addUrlPatterns("/jCaptcha");
registration.setEnabled(Boolean.TRUE);
registration.setName("JCaptchaFilter");
registration.setAsyncSupported(Boolean.TRUE);
return registration;
}
}