写在前面
如果图片显示不清楚的,可以右键图片,选择在新标签页中打开图片
shiro是什么,shiro做了哪些事,shiro的主要功能,请参考shiro官网,博主这里会带大家走一遍在JEECMS中的配置和一些shiro的核心代码和运行原理,最后再带大家走一遍认证和授权的流程。
一.Spring集成Shiro
web.xml首先加载shiro-context.xml配置文件,然后DelegatingFilterProxy才能在容器中找到shiroFilter,然后将shiroFilter注入到自己的delegate属性中,进行shiro过滤器的委派调用,实现shiro安全框架的集成
二.shiro-context.xml文件配置
shiro-context.xml文件位置请参考JEECMS——项目包结构。shiro安全框架的配置全在此配置文件内,下面对JEECMS的配置进行细化讲解,而shiro的配置即是对org.apache.shiro.spring.web.ShiroFilterFactoryBean的属性配置,在JEECMS中配置了以下几方面
配置 | 定义 |
---|---|
securityManager | 安全管理器 |
loginUrl | 认证登录地址 |
successUrl | 成功跳转地址 |
filters | ShiroFilterFactoryBean中的Map类型属性filters |
filterChainDefinitions | 过滤映射定义:anon匿名 authc登录认证 user用户已登录 logout退出 |
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jspx" />
<property name="successUrl" value="/" />
<property name="filters">
<util:map>
<entry key="authc" value-ref="authcFilter" />
<entry key="user" value-ref="userFilter" />
<entry key="logout" value-ref="logoutFilter" />
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
*.jspx = anon
*.jhtml = anon
/member/forgot_password.jspx = anon
/member/password_reset.jspx = anon
/member/jobapply.jspx = anon
/login.jspx = authc
/logout.jspx = logout
/member/** = user
/jeeadmin/jeecms/login.do = authc
/jeeadmin/jeecms/logout.do = logout
/jeeadmin/jeecms/** =user
</value>
</property>
</bean>
securityManager
配置安全管理器即配置DefaultWebSecurityManager对象,在这里JEECMS配置了三个属性:缓存管理,记住我和认证授权realm
属性 | 定义 |
---|---|
cacheManager | 缓存管理器 |
rememberMeManager | 记住我管理器 |
realm | 认证授权realm |
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="shiroEhcacheManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="realm" ref="authorizingRealm" />
</bean>
1.cacheManager ——缓存管理器
DefaultWebSecurityManager父类CachingSecurityManager当中的一个属性,提供缓存支持
<!-- SHIRO缓存管理器 -->
<!-- 也可以直接使用MemoryConstrainedCacheManager -->
<!-- 这里有两种方式注入cacheManager,一种直接提供一个CacheManager,另一种是不提供
CacheManager通过扫描文件位置惰性加载一个CacheManager,这里使用的是第一种方式 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- 这个被注掉了,项目中也没有ehcache-shiro.xml文件-->
<!--
<property name="cacheManagerConfigFile">
<value>classpath:ehcache-shiro.xml</value>
</property>
-->
<!-- 在cache-context.xml中配置了cacheManager的bean -->
<property name="cacheManager">
<ref local="cacheManager"/>
</property>
</bean>
<!-- 这个是cache-context.xml中的配置,博主被大家放到一起- -->
<bean id="cacheManager" class="com.jeecms.common.web.WebEhCacheManagerFacotryBean">
<property name="cacheManagerName" value="cacheManager"/>
<property name="configLocation">
<value>classpath:ehcache.xml</value>
</property>
<!-- 保存cache的位置 -->
<property name="diskStoreLocation">
<value>/WEB-INF/cache</value>
</property>
</bean>
2.rememberMeManager——记住我
DefaultWebSecurityManager父类DefaultSecurityManager当中的一个属性,负责在session中记住一个subject的标识
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- 秘钥 -->
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
<!-- shiro自定义的cookie继承自cookie -->
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的名字rememberMe -->
<constructor-arg value="rememberMe"/>
<!-- 这个可以不配置,默认就是true -->
<property name="httpOnly" value="true"/>
<!-- 存活时间,不随浏览器关闭而销毁 -->
<property name="maxAge" value="31536000"/>
</bean>
3.realm——认证授权realm
DefaultWebSecurityManager父类RealmSecurityManager当中有一个Collection类型的属性叫realms,realm被添加到此集合中。自定义的CmsAuthorizingRealm覆盖了认证和授权两个方法
<!-- 认证授权realm -->
<bean id="authorizingRealm" class="com.jeecms.core.security.CmsAuthorizingRealm">
<!-- 父类AuthenticatingRealm中的一个属性 -->
<property name="credentialsMatcher">
<!-- 确定身份验证令牌提供的凭证是否与存储在系统中的对应帐户的凭据相匹配 -->
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 指定hash算法:MD5,SHA1等 -->
<property name="hashAlgorithmName" value="MD5"/>
<!-- true为hex编码, false为base64编码 -->
<property name="storedCredentialsHexEncoded" value="true"/>
<!-- 迭代次数 -->
<property name="hashIterations" value="1" />
</bean>
</property>
<!-- 自定义的CmsAuthorizingRealm的一个属性,在jeecms-core.xml中配置的bean,作用是用来获取数据库用户数据 -->
<property name="cmsUserMng" ref="cmsUserMng" />
</bean>
filters
一般情况下我们是不需要配置filters的,这里JEECMS自定义了一系列filter对默认的filter进行了覆盖,在自定义的filter里加入了一些JEECMS自己的功能业务逻辑
关键字 | 默认映射的filter | 替代的filter |
---|---|---|
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | com.jeecms.core.security.CmsAuthenticationFilter |
user | org.apache.shiro.web.filter.authc.UserFilter | com.jeecms.core.security.CmsUserFilter |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | com.jeecms.core.security.CmsLogoutFilter |
<!-- 这一段是从shiroFilter配置中摘出来的 -->
<property name="filters">
<util:map>
<entry key="authc" value-ref="authcFilter" />
<entry key="user" value-ref="userFilter" />
<entry key="logout" value-ref="logoutFilter" />
</util:map>
</property>
<!-- 作为parent的Bean,做到最大化的重用 -->
<bean id="adminUrlBean" class="com.jeecms.core.security.CmsAdminUrl">
<property name="adminLogin" value="/jeeadmin/jeecms/login.do"/>
<property name="adminPrefix" value="/jeeadmin/jeecms/"/>
</bean>
<!-- 自定义登录认证filter -->
<bean id="authcFilter" class="com.jeecms.core.security.CmsAuthenticationFilter" parent="adminUrlBean">
<property name="adminIndex" value="/jeeadmin/jeecms/index.do"/>
</bean>
<!-- 自定义验证用户是否登录filter -->
<bean id="userFilter" class="com.jeecms.core.security.CmsUserFilter" parent="adminUrlBean"/>
<!-- 自定义注销过滤器 -->
<bean id="logoutFilter" class="com.jeecms.core.security.CmsLogoutFilter" parent="adminUrlBean"/>
filterChainDefinitions
shiro功能filter的路径映射,对不同请求,执行不同的filter,达到不同的功能效果
关键字 | 映射路径 |
---|---|
authc | /login.jspx | /jeeadmin/jeecms/login.do |
user | /member/** | /jeeadmin/jeecms/** |
logout | /logout.jspx | /jeeadmin/jeecms/logout.do |
anon | *.jspx | *.jhtml | /member/forgot_password.jspx | /member/password_reset.jspx | /member/jobapply.jspx |
lifecycleBeanPostProcessor
<!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
开启shiro权限注解
三.JEECMS中shiro登录认证的执行流程
上面列出了shiro的所有配置,并且大致描述了他们的配置作用,现在,带大家跑一遍登录认证的流程,看看登录认证在shiro里是如何执行的
1.项目启动实例化Shiro组件
2.请求到来处理流程
我们模拟一个login.jspx请求
通过上面图片中的描述,经过shiro内部的过滤器链,进入登录的执行方法executeLogin()
通过subject的login方法,进入我们自定义的认证realm的doGetAuthenticationInfo方法,这也是需要我们做的最后一步了,剩下的全权交给shiro即可
四.JEECMS中shiro授权的执行流程
jeecms使用的是shiro的注解式权限控制,我们这里就模拟访问一个被权限注解标记的一个接口方法,这里我们直接给出调用流程和讲解,如有不解我们可以在讨论区讨论
授权到底做了哪些事
五.总结
JEECMS中使用shiro的部分大致就是这样,具体shiro框架的东西博主以后会开个专题去说(分类早就建好了就是没有更新。。),如果有什么具体的问题可以留言,博主看到会第一时间回复。
系列章节链接直达
JEECMS——前言
JEECMS——源码下载和安转运行
JEECMS——项目包结构
JEECMS——web.xml配置
JEECMS——过滤器和拦截器