shiro配合spring
1.配置SecurityManager
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/>
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="sessionMode" value="native"/>
<property name="realm" ref="jdbcRealm"/>
</bean>
2.配置CacheManager
2.1 需要加入ehcache的jar包和配置文件
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- Set a net.sf.ehcache.CacheManager instance here if you already have one. If not, a new one
will be creaed with a default config:
<property name="cacheManager" ref="ehCacheManager"/> -->
<!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
a specific Ehcache configuration to be used, specify that here. If you don't, a default
will be used.:
<property name="cacheManagerConfigFile" value="classpath:some/path/to/ehcache.xml"/> -->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>
3.配置Realm
3.1 直接配置实现了org.apache.shiro.realm.Realm接口的bean
<bean id="jdbcRealm" class="com.kioluo.shiro.realms.ShiroRealm">
</bean>
4.配置LifecycleBeanPostProcessor,可以自定的来调用配置在spring IOC容器中的shiro bean生命周期方法
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
5.启用IOC容器中的shiro注解,但必须在配置了LifecycleBeanPostProcessor之后才可以使用
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
6.配置ShiroFilter
6.1 id必须和web.xml中的DelegatingFilterProxy的
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/user.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter bean
defined will be automatically acquired and available via its beanName in chain
definitions, but you can perform overrides or parent/child consolidated configuration
here if you like: -->
<!-- <property name="filters">
<util:map>
<entry key="aName" value-ref="someFilterPojo"/>
</util:map>
</property> -->
<property name="filterChainDefinitions">
<value>
/login = anon
# everything else requires authentication:
/** = authc
</value>
</property>
</bean>
6.2 URL匹配模式
- ?(一个字符)
- *(零或多个字符)
- **(零或多个路径)
原则:第一次匹配优先
认证思路
- 获取当前的Subject,调用SecurityUtils.getSubject();
- 测试当前的用户是否已经被认证,即是否已经登录,调用Subject的isAuthenticated()
- 若没有被认证,则把用户名和密码封装为UsernamePasswordToken对象
- 执行登录:调用Subject的login(AuthenticationToken)方法
- 自定义Realm方法,从数据库中获取对应的记录,返回给Shiro
5.1 实际上需要继承org.apache.shiro.realm.AuthenticatingRealm类
5.2 实现doGetAuthenticationInfo(AuthenticationToken)方法 - 由shiro完成密码的比对(通过AuthenticatingRealm的credentialsMatcher属性来进行密码的比对)
6.1 MD5加密,配置credentialsMatcher为HashedCredentialsMatcher,hashAlgorithmName为MD5
6.2 MD5盐值加密
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realm);
Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
7.多Realm认证,配置org.apache.shiro.authc.pam.ModularRealmAuthenticator(默认是AtLeastOneSuccessfulStrategy)
8.AuthenticationStrategy接口(三种实现FirstSuccessfulStrategy, AtLeastOneSuccessfulStragegy, AllSuccessfulStrategy)
授权方式
- 编程式
- 注解式
- JSP/GSP标签
身份验证
拦截器名:authc、authcBasic、logout、user、anon
授权实现
授权需要继承AuthorizingRealm类,并实现其doGetAuthorizationInfo方法
AuthorizingRealm类继承自AuthenticatingRealm,但没有实现AuthenticatingRealm中的doGetAuthenticationInfo,所以认证和授权只需要继承AuthorizingRealm就可以了,同时实现他的两个抽象方法
实现doGetAuthorizationInfo方法:
- 从PrincipalCollection中来获取登录用户的信息
- 利用登陆的用户的信息来获取当前用户的角色或权限(可能需要查询数据库)
- 创建SimpleAuthorizationInfo,并设置其roles属性
- 返回SimpleAuthorizationInfo对象
Shiro标签
JSTL标签
<shiro:guest>...</shiro:guest>
<shiro:user>...</shiro:user>
<shiro:principal property="username" />
<shiro:hasRole name="admin">...</shiro:hasRole>
权限注解
@RequiresAuhtentication
@RequiresUser
@RequiresGuest
@RequiresRoles(value={"admin", "user"}, logical=Logical.AND)
@RequiresPermissions(value={"user:a", "user:b"}, logical=Logical.OR)
从数据表初始化资源和授权
配置一个bean,该bean实际上是一个Map。通过实例工厂方法的方式获取
<bean id="factory" factory-bean="filterChainDefinitionFactory" factory-method="buildFilterChainDefinition"/>
<bean id="filterChainDefinitionFactory"
class="com.kioluo.shiro.factorys.FilterChainDefinitionFactory"/>
设置ShiroFilterFactoryBean的property
<property name="filterChainDefinitionMap" ref="factory" />
会话管理
controller层的HttpSession可以在service层通过shiro的会话管理得到
SecurityUtils.getSubject().getSession();
SessionDAO接口及其实现类
AbstractSessionDAO、CachingSessionDAO、MemorySessionDAO、EnterpriseCacheSessionDAO
session配置
- Session ID生成器
- SessionDAO实现,继承EnterpriseCacheSessionDAO
- 会话管理器
会话验证
会话验证调度器SessionValidationScheduler、QuartzSessionValidationScheduler