在web环境下搭建shiro框架

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

<context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:applicationContext.xmlparam-value>
    context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>
    <servlet>
        <servlet-name>springmvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:mvc.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>springmvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

3.在classpath路径下创建spring的配置文件applicationContext.xml和spring mvc的配置文件mvc.xml
mvc.xml文件


<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"/>
        
        <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目录下。

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

除此之外,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> -->
        
        <property name="filterChainDefinitions">
            <value>
            
                /logo.jsp = anon
            
                /** = authc
            value>
        property>
    bean>

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

最后,applicationContext.xml中的完整代码如下:


<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 id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <property name="sessionMode" value="native"/>
        
        <property name="realm" ref="jdbcRealm"/>
    bean>

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

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


    

     
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.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>
    
    <bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
        <property name="securityManager" ref="securityManager"/>
    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> -->
        
        <property name="filterChainDefinitions">
            <value>
            
                /logo.jsp = anon
            
                /** = 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框架。

你可能感兴趣的:(Java)