Shiro集成spring--权限管理

时间:2022-11-25 15:21:42

Shiro与Spring Security类似是都是用作权限管理,它们的控制粒度都能达到按钮级别。其实在正常使用中已经足够了,那么本次主要记录一下Shiro和Spring的集成,具体如下:


Shiro是通过过滤器的方式,对访问路径拦截,并进行权限的控制。那么首先,需要在web.xml中设置一个过滤器

<!-- 配置shiro   start -->
<!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 -->
<!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> -->
<!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 -->
<!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置shiro end -->

以上我们看到一个代理过滤器shiroFilter,这个shiroFilter实在spring中使用bean的形式定义的
<!-- 这个id得和web.xml中shiro的filter-name相对应 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
<property name="loginUrl" value="/toLogin.do"/>
<!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了)
<property name="successUrl" value=""/> -->
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp-->
<property name="unauthorizedUrl" value="/unauth.do"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->
<!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()项目路径的值来的 -->
<!-- anon:它对应的过滤器里面是空的,什么都没做,不验证,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 -->
<!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->
<property name="filterChainDefinitions">
<value>
/toLogin**=anon <!-- 不需要验证 -->
/login**=anon <!-- 不需要验证 -->
/unauth**=anon <!-- 不需要验证 -->
/mycode.jpg=anon
/static/** = anon
/common/** = anon
/service/** = anon
/** = authc <!-- 需要认证 -->
</value>
</property>
</bean>
以上每个参数注释已经很详细,就不再多舌。shiroFilter的配置还需要一个安全处理的核心securityManager,具体配置如下:
<!--安全管理器-->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <!--设置自定义Realm-->        <property name="realm" ref="shiroDbRealm"/>    </bean><!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的ShiroDbRealm.java -->     <bean id="shiroDbRealm" class="com.enker.manager.shiro.ShiroDbRealm">            </bean>
以上安全管理器还需要一个realm,其实这个类中主要是用来进行登录验证及权限验证的。这个需要我们自己独立实现,继承与AuthorizingRealm,主要实现两个方法

//登录验证

protected AuthenticationInfo doGetAuthenticationInfo

//权限验证

protected AuthorizationInfo doGetAuthorizationInfo


当然除了以上配置实现外,还需要配置:

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
LifecycleBeanPostProcessor用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调,在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调。如UserRealm就实现了Initializable,而DefaultSecurityManager实现了Destroyable。具体可以查看它们的继承关系。



在登录代码中我们还需要手动调用login方法,执行登录操作。具体如下:

UsernamePasswordToken token = new UsernamePasswordToken(userName,password,rememberMe);
SecurityUtils.getSubject().login(token);


可能参考博文:http://jinnianshilongnian.iteye.com/blog/2029717/