在web环境下搭建shiro框架

来源:互联网 发布:能以礼让为国乎 编辑:程序博客网 时间:2024/04/30 10:13

上节讲了在JAVA SE环境下搭建shiro框架,这节主要在web环境下搭建shiro框架对web前端页面进行权限的控制。
一,整合spring,springmvc框架。
1.导入spring的相关jar包。
2.配置web.xml文件

<context-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:applicationContext.xml</param-value>    </context-param>    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <servlet>        <servlet-name>springmvc</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <init-param>            <param-name>contextConfigLocation</param-name>            <param-value>classpath:mvc.xml</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>springmvc</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping>

3.在classpath路径下创建spring的配置文件applicationContext.xml和spring mvc的配置文件mvc.xml
mvc.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:p="http://www.springframework.org/schema/p"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc"    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/mvc        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="prefix" value="/"></property>        <property name="suffix" value=".jsp"></property>     </bean>        <!-- 配置注解扫描器 -->        <context:component-scan base-package="cn.shinelon.controller"></context:component-scan></beans>

接着自行创建mvc.xml文件,至此,基本完成了spring,springmvc框架的整合
下面,重点是applicationContext.xml文件,以及web.xml文件的配置。

二,整合shiro框架
首先,我们来简单讲解一下shiro框架整合的原理。

对于一个安全框架,它控制着用户对web资源的访问,当服务器启动,用户发来请求,首先应该经过安全验证,哪些资源用户可以直接匿名访问,哪些资源用户需要登录验证身份才能访问,这里我们想到了在web.xml文件中配置过滤器,用户从前台进行请求,首先经过springmvc的servlet请求,请求到相应的资源,这是到了shiro过滤器,必须经过验证,需要强调的时,web.xml文件的filter只是一个代理类DelegatingFilterProxy,它需要到applicationContext.xml文件中找到与filter-name名相同的bean进行权限的管理,这里又有一个问题,为什么要使用代理类,这个类有什么作用?使用代理类可以降低代码的耦合度,提高代码的重用性,比如,你要使用spring security安全框架的时候,web.xml文件中的filter代理类无需更改,它只是一个代理,只需改动相应的bean就可以了,这样一来,在web.xml中对权限的控制有一个总的代理,一切的外来请求首先通过这个代理来进行权限的验证,比如,你要去找一个公司找人,首先要经过前台保卫室的身份认证,经过了验证你就可以找到你要找的人,就是这个道理。在这里有一个代理类DelegatingFilterProxy,首先我们先看一下它的源码:

public class DelegatingFilterProxy extends GenericFilterBean {    private String contextAttribute;    private WebApplicationContext webApplicationContext;    private String targetBeanName;    private boolean targetFilterLifecycle = false;    private volatile Filter delegate;    private final Object delegateMonitor = new Object();    .......    }

首先说一下targetBeanName这个属性,从字面意思上我们可以看出来它是目标bean的名称,也就是说默认情况下,filter-name的名字必须与bean的名字一致,但在这里也可以显示的指出目标bean的名字,也就是说通过设置targetBeanName这个属性的值可以不用使他们的值一致。下面看一段源码就会更加清楚它的工作原理了:

    @Override    protected void initFilterBean() throws ServletException {        synchronized (this.delegateMonitor) {            if (this.delegate == null) {                // If no target bean name specified, use filter name.                if (this.targetBeanName == null) {                    this.targetBeanName = getFilterName();                }                // Fetch Spring root application context and initialize the delegate early,                // if possible. If the root application context will be started after this                // filter proxy, we'll have to resort to lazy initialization.                WebApplicationContext wac = findWebApplicationContext();                if (wac != null) {                    this.delegate = initDelegate(wac);                }            }        }    }

接着,我们来说另一个核心配置,在applicationContext.xml文件中配置SecurityManager。

 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="cacheManager" ref="cacheManager"/>        <property name="sessionMode" value="native"/>        <!-- realm实现类 -->        <property name="realm" ref="jdbcRealm"/>    </bean>

这里创建securityManager安全管理器bean,它有几个属性,cacheManager这个是缓存管理,这个缓存技术,是hibernate中默认的缓存框架,第二个属性sessionMode这个是session的模式,在这里作用不大,就不做详细讲解了,最后一个属性是real,它引入了一个realm的bean实例,这里我们在src文件中创建一个ShiroRealm类实现realm接口,代码如下:

import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.realm.Realm;public class ShiroRealm implements Realm {    @Override    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken arg0)            throws AuthenticationException {        // TODO Auto-generated method stub        return null;    }    @Override    public String getName() {        // TODO Auto-generated method stub        return null;    }    @Override    public boolean supports(AuthenticationToken arg0) {        // TODO Auto-generated method stub        return false;    }}

接着在spring配置文件中注入bean

 <bean id="jdbcRealm" class="cn.shinelon.shiro.ShiroRealm"></bean>

然后就是配置cacheManager,这里面需要加入另外一个配置文件ehcache.xml,这个文件读者可以在hibernate的jar包中找到拿到项目的src目录下。

 <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>    </bean>

除此之外,applicationContext.xml文件中还有一个重要的配置,就是上文所说的filter代理类的目标bean:

     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager"/>        <property name="loginUrl" value="/logon.jsp"/>        <property name="successUrl" value="/success.jsp"/>        <property name="unauthorizedUrl" value="/error.jsp"/>            <util:map>                <entry key="aName" value-ref="someFilterPojo"/>            </util:map>        </property> -->        <!-- 代表我们要完成的shiro过滤器的具体配置 -->        <property name="filterChainDefinitions">            <value>            <!-- 表示logon.jsp不需要认证即可访问 -->                /logo.jsp = anon            <!-- 除了logon.jsp外,其他的web资源都需要认证才能访问 -->                /** = authc            </value>        </property>    </bean>

第一个属性是引入了安全管理器,第二个属性是登录页面它的值是anon,也就是所有的用户不用登录就可以匿名访问的,不需要任何权限,第三个属性是当登录成功后跳转的页面,最后一个没有经过验证后跳转的页面。

最后,applicationContext.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:p="http://www.springframework.org/schema/p"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc"    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/mvc        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx.xsd">         <!-- 安全管理器bean:            1.缓存技术:缓存管理cacheManager            2.realm:负责获取存储数据          -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="cacheManager" ref="cacheManager"/>        <property name="sessionMode" value="native"/>        <!-- realm实现类 -->        <property name="realm" ref="jdbcRealm"/>    </bean>    <bean id="jdbcRealm" class="cn.shinelon.shiro.ShiroRealm"></bean>    <!-- 可以使用缓存技术        hibernate中默认的EHCACH缓存框架     -->    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>    </bean>    <!-- =========================================================         Shiro Spring-specific integration         ========================================================= -->     <!-- 必须要有这样的实例,用来管理spring容器当中的shiro常见的对象 -->    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>      <!-- 启用shiro注解 -->    <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>    <!-- 网络方面 -->    <bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">        <property name="securityManager" ref="securityManager"/>    </bean>    <!-- 配置shiroFilter        1.shiroFilter这个bean必须与web.xml文件中的filter-name保持一致     -->    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager"/>        <property name="loginUrl" value="/logon.jsp"/>        <property name="successUrl" value="/success.jsp"/>        <property name="unauthorizedUrl" value="/error.jsp"/>            <util:map>                <entry key="aName" value-ref="someFilterPojo"/>            </util:map>        </property> -->        <!-- 代表我们要完成的shiro过滤器的具体配置 -->        <property name="filterChainDefinitions">            <value>            <!-- 表示logon.jsp不需要认证即可访问 -->                /logo.jsp = anon            <!-- 除了logon.jsp外,其他的web资源都需要认证才能访问 -->                /** = authc            </value>        </property>    </bean>     <context:component-scan base-package="cn.shinelon"/></beans>

在这里,shiro使用Ant风格的url匹配规则
/aa?.jsp中的?只匹配一个字符,表示aab.jsp页面,只能匹配b这一个字符。
/aa*.jsp中的 *号表示匹配零个或者多个字符,表示以aa开头的所有jsp页面
/** 是路径,表示匹配web根目录下的所有路径。
shiro中url的匹配顺序采用第一个匹配优先的原则。

接着就是测试了,在根目录下创建相应的登录页面logon.jsp,success.jsp,error.jsp页面,由于没有连接数据库,只做一个简单的测试,我们在浏览器中输入localhost:8080/项目名/logon.jsp时可以直接访问,但是,如果直接访问success.jsp就会重定向到logon.jsp,这说明用户没有权限访问。至此,我们就搭建完了web环境下的shiro框架。

原创粉丝点击