springboot集成shiro的示例分析
我们开发时候有时候要把传统spring shiro转成spring boot项目,或者直接集成,name我们要搞清楚一个知识,就是 xml配置和spring bean代码配置的关系,这一点很重要,因为spring boot是没有xml配置文件的(也不绝对,spring boot也是可以引用xml配置的)
引入依赖:
<dependency>
<artifactId>ehcache-core</artifactId>
<groupId>net.sf.ehcache</groupId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
如果你出现错误 找不到slf4j,引入依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
传统xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.198bona.com
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.len"/>
<!--定义realm-->
<bean id="myRealm" class="com.len.core.shiro.LoginRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<bean id="permissionFilter" class="com.len.core.filter.PermissionFilter"/>
<!--目前去掉自定义拦截验证 由个人处理登录业务-->
<!--<bean id="customAdvicFilter" class="com.len.core.filter.CustomAdvicFilter">
<property name="failureKeyAttribute" value="shiroLoginFailure"/>
</bean>-->
<bean id="verfityCodeFilter" class="com.len.core.filter.VerfityCodeFilter">
<property name="failureKeyAttribute" value="shiroLoginFailure"/>
<property name="jcaptchaParam" value="code"/>
<property name="verfitiCode" value="true"/>
</bean>
<!-- Shiro过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="unauthorizedUrl" value="/goLogin" />
<property name="filters">
<map>
<entry key="per" value-ref="permissionFilter"/>
<entry key="verCode" value-ref="verfityCodeFilter"/>
<!--<entry key="main" value-ref="customAdvicFilter"/>-->
</map>
</property>
<property name="filterChainDefinitions">
<value>
<!-- /** = anon所有url都可以匿名访问 -->
/login = verCode,anon
/getCode = anon
/logout = logout
/plugin/** = anon
<!-- /** = authc 所有url都必须认证通过才可以访问-->
/user/**=per
<!-- /login = main-->
/** = authc
</value>
</property>
</bean>
<!--安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<property name="cacheManager" ref="cacheManager" />
<!--<property name="rememberMeManager" ref="rememberMeManager" />-->
</bean>
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher"
class="com.len.core.shiro.RetryLimitCredentialsMatcher">
<constructor-arg index="0" ref="cacheManager"/>
<constructor-arg index="1" value="5"/>
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="4"/>
</bean>
<!--缓存-->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache/ehcache.xml"/>
</bean>
<!--开启注解-->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
转换成bean 新建类ShiroConfig
@Configuration
public class ShiroConfig {
@Bean
public RetryLimitCredentialsMatcher getRetryLimitCredentialsMatcher(){
RetryLimitCredentialsMatcher rm=new RetryLimitCredentialsMatcher(getCacheManager(),"5");
rm.setHashAlgorithmName("md5");
rm.setHashIterations(4);
return rm;
}
@Bean
public LoginRealm getLoginRealm(){
LoginRealm realm= new LoginRealm();
realm.setCredentialsMatcher(getRetryLimitCredentialsMatcher());
return realm;
}
@Bean
public EhCacheManager getCacheManager(){
EhCacheManager ehCacheManager=new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache/ehcache.xml");
return ehCacheManager;
}
@Bean
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(){
DefaultWebSecurityManager dwm=new DefaultWebSecurityManager();
dwm.setRealm(getLoginRealm());
dwm.setCacheManager(getCacheManager());
return dwm;
}
@Bean
public PermissionFilter getPermissionFilter(){
PermissionFilter pf=new PermissionFilter();
return pf;
}
@Bean
public VerfityCodeFilter getVerfityCodeFilter(){
VerfityCodeFilter vf= new VerfityCodeFilter();
vf.setFailureKeyAttribute("shiroLoginFailure");
vf.setJcaptchaParam("code");
vf.setVerfitiCode(true);
return vf;
}
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(){
ShiroFilterFactoryBean sfb = new ShiroFilterFactoryBean();
sfb.setSecurityManager(getDefaultWebSecurityManager());
sfb.setLoginUrl("/login");
sfb.setUnauthorizedUrl("/goLogin");
Map<String, Filter> filters=new HashMap<>();
filters.put("per",getPermissionFilter());
filters.put("verCode",getVerfityCodeFilter());
sfb.setFilters(filters);
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/login","verCode,anon");
//filterMap.put("/login","anon");
filterMap.put("/getCode","anon");
filterMap.put("/logout","logout");
filterMap.put("/plugin/**","anon");
filterMap.put("/user/**","per");
filterMap.put("/**","authc");
sfb.setFilterChainDefinitionMap(filterMap);
return sfb;
}
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor as=new AuthorizationAttributeSourceAdvisor();
as.setSecurityManager(getDefaultWebSecurityManager());
return as;
}
@Bean
public FilterRegistrationBean delegatingFilterProxy(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
proxy.setTargetFilterLifecycle(true);
proxy.setTargetBeanName("shiroFilter");
filterRegistrationBean.setFilter(proxy);
return filterRegistrationBean;
}
其中有个别类是自定义的拦截器和 realm,此时spring 即能注入shiro 也就是 spring boot集成上了 shiro
如果你因为其他配置引起一些失败,可以参考开源项目 lenos快速开发脚手架 spring boot版本,其中有对shiro的集成。