四、spring+shiro 入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mr_yangzc/article/details/81512761

首先搭建springmvc+spring 框架
pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <name>samples</name>
    <groupId>com.shiro</groupId>
    <artifactId>samples</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- spring version -->
        <spring.version>4.3.13.RELEASE</spring.version>
        <shiro.version>1.4.0</shiro.version>
    </properties>

    <dependencies>


        <!--  shiro start -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>

        <!--  shiro end -->


        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- spring aop-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        

        <!-- jstl 标签库 -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!--Shiro过滤器-->
    <!--<filter>-->
    <!--<filter-name>shiroFilter</filter-name>-->
    <!--<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>-->
    <!--<init-param>-->
    <!--<param-name>targetFilterLifecycle</param-name>-->
    <!--<param-value>true</param-value>-->
    <!--</init-param>-->
    <!--</filter>-->
    <!--<filter-mapping>-->
    <!--<filter-name>shiroFilter</filter-name>-->
    <!--<url-pattern>/*</url-pattern>-->
    <!--<dispatcher>REQUEST</dispatcher>-->
    <!--<dispatcher>FORWARD</dispatcher>-->
    <!--<dispatcher>INCLUDE</dispatcher>-->
    <!--<dispatcher>ERROR</dispatcher>-->
    <!--</filter-mapping>-->


    <filter>
        <filter-name>springRestFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>springRestFilter</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>


    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-context.xml</param-value>
    </context-param>


    <servlet>
        <servlet-name>SpringMVCConfig</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringMVCConfig</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

配置 application-context.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:task="http://www.springframework.org/schema/task"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
      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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!--<context:property-placeholder location="classpath:bjfccp.properties"/>-->
    <!--ignore-unresolvable="true"-->
    <import resource="spring-mvc.xml"/>

</beans>

spring-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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        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-4.3.xsd">
    <!-- 配置扫描controller包 -->
    <context:component-scan base-package="spring"/>

    <!-- 注册HandlerMapper、HandlerAdapter两个映射类 -->
    <mvc:annotation-driven/>
    <!-- 访问静态资源 -->
    <mvc:default-servlet-handler/>
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/views/"
          p:suffix=".jsp"/>

</beans>

故事到这里就已经搭建好spring+springmvc了
教你一个 小技巧 (异常处理)有兴趣可以去看看https://blog.csdn.net/Mr_yangzc/article/details/81512939

运行起来以后不报错 开始搭建 spring+shiro
https://shiro.apache.org/spring-xml.html
pom.xml

参考:
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- spring version -->
    <spring.version>4.3.13.RELEASE</spring.version>
    <shiro.version>1.4.0</shiro.version>
 </properties>
加入:
<!--  shiro start -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>${shiro.version}</version>
</dependency>

<!--  shiro end -->

web.xml https://shiro.apache.org/web.html#web-xml

<!--Shiro过滤器-->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

配置 spring-shiro 配置文件

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        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-4.3.xsd">
    <!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的UserRealm.java -->
    <bean id="myRealm" class="spring.shiro.realm.MyRealm">
        <property name="credentialsMatcher" ref="md5Matcher"/>
        <!--<property name="credentialsMatcher" ref="md5hash"/>-->
    </bean>

    <bean id="md5hash" class="spring.shiro.matcher.Md5HashCredentialsMatcher"/>

    <bean id="md5Matcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!-- 加密算法的名称 -->
        <property name="hashAlgorithmName" value="MD5"/>
        <!-- 配置加密的次数 -->
        <property name="hashIterations" value="1024"/>
    </bean>


    <bean id="sha1Matcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!-- 加密算法的名称 -->
        <property name="hashAlgorithmName" value="SHA1"/>
        <!-- 配置加密的次数 -->
        <property name="hashIterations" value="1024"/>
    </bean>

    <bean id="firstRealm" class="spring.shiro.realm.FirstRealm">
        <property name="credentialsMatcher" ref="md5Matcher"/>
    </bean>

    <bean id="secondRealm" class="spring.shiro.realm.SecondRealm">
        <property name="credentialsMatcher" ref="sha1Matcher"/>
        <!--<property name="credentialsMatcher" ref="md5hash"/>-->
    </bean>


    <!-- Shiro默认会使用Servlet容器的Session,可通过sessionMode属性来指定使用Shiro原生Session -->
    <!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <!--<property name="realm" ref="myRealm"/>-->
        <!--<property name="realms">-->
        <!--<list>-->
        <!--<ref bean="firstRealm"/>-->
        <!--<ref bean="secondRealm"/>-->
        <!--</list>-->
        <!--</property>-->
        <property name="authenticator" ref="authenticator"/>
        <property name="authorizer" ref="authorizer"/>
    </bean>

    <bean id="authorizer" class="org.apache.shiro.authz.ModularRealmAuthorizer">
        <property name="realms">
            <list>
                <ref bean="firstRealm"/>
                <ref bean="secondRealm"/>
            </list>

        </property>
    </bean>


    <!--多个realm 配置-->
    <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
        <!--配置认证策略-->
        <property name="authenticationStrategy" ref="atLeastOneSuccessfulStrategy"/>
        <property name="realms">
            <list>
                <ref bean="firstRealm"/>
                <ref bean="secondRealm"/>
            </list>
        </property>
    </bean>
    <!--全部通过-->
    <bean id="allSuccessfulStrategy" class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"/>
    <!--只有第一个验证通过,才会视为整体认证通过。其他的会被忽略。-->
    <bean id="firstSuccessfulStrategy" class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
    <!--默认-->
    <bean id="atLeastOneSuccessfulStrategy" class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"/>

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

    <!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->
    <!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->

    <bean id="shiroFilter22" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.html"页面 -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 登录成功后要跳转的连接 -->
        <property name="successUrl" value="/index.jsp"/>
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!-- 用户访问未对其授权的资源时,所显示的连接 -->
        <!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp -->
        <!-- <property name="unauthorizedUrl" value="/no_permissions.jsp" />  -->
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <!-- 此处可配合我的这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 -->
        <!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 -->
        <!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 -->
        <!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->
        <property name="filters">
            <map>
                <!--<entry key="kickout" value-ref="kickoutSessionControlFilter"/>-->
            </map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                <!-- anon表示此地址不需要任何权限即可访问 -->
                <!--/a?.html =anon-->
                <!--/a.html = authc-->
                <!--/a**.html = anon-->
                <!--# /admin/** = authc, roles[admin]-->
                <!--# /docs/** = authc, perms[document:read]-->
                /login**=anon
                <!--/admin=roles[admin]-->
                <!--/user=roles[user]-->
                /static/** = anon
                /** = authc
            </value>
        </property>
    </bean>
    <!--<bean id="kickoutSessionControlFilter" class="spring.shiro.filter.MyFilter"/>-->

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 注解授权:AOP式方法级权限检查  -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"/>
    </bean>

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
</beans>

ehcache.xml

<!--
  ~ Licensed to the Apache Software Foundation (ASF) under one
  ~ or more contributor license agreements.  See the NOTICE file
  ~ distributed with this work for additional information
  ~ regarding copyright ownership.  The ASF licenses this file
  ~ to you under the Apache License, Version 2.0 (the
  ~ "License"); you may not use this file except in compliance
  ~ with the License.  You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing,
  ~ software distributed under the License is distributed on an
  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  ~ KIND, either express or implied.  See the License for the
  ~ specific language governing permissions and limitations
  ~ under the License.
  -->

<!-- EhCache XML configuration file used for Shiro spring sample application -->
<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

If the path is a Java System Property it is replaced by
its value in the running VM.

The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir/shiro-spring-sample"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
    the CacheManager.

    The following attributes are required:

    maxElementsInMemory            - Sets the maximum number of objects that will be created in memory
    eternal                        - Sets whether elements are eternal. If eternal,  timeouts are ignored and the
                                     element is never expired.
    overflowToDisk                 - Sets whether elements can overflow to disk when the in-memory cache
                                     has reached the maxInMemory limit.

    The following attributes are optional:
    timeToIdleSeconds              - Sets the time to idle for an element before it expires.
                                     i.e. The maximum amount of time between accesses before an element expires
                                     Is only used if the element is not eternal.
                                     Optional attribute. A value of 0 means that an Element can idle for infinity.
                                     The default value is 0.
    timeToLiveSeconds              - Sets the time to live for an element before it expires.
                                     i.e. The maximum time between creation time and when an element expires.
                                     Is only used if the element is not eternal.
                                     Optional attribute. A value of 0 means that and Element can live for infinity.
                                     The default value is 0.
    diskPersistent                 - Whether the disk store persists between restarts of the Virtual Machine.
                                     The default value is false.
    diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
                                     is 120 seconds.
    memoryStoreEvictionPolicy      - Policy would be enforced upon reaching the maxElementsInMemory limit. Default
                                     policy is Least Recently Used (specified as LRU). Other policies available -
                                     First In First Out (specified as FIFO) and Less Frequently Used
                                     (specified as LFU)
    -->

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />

    <!-- We want eternal="true" (with no timeToIdle or timeToLive settings) because Shiro manages session
expirations explicitly.  If we set it to false and then set corresponding timeToIdle and timeToLive properties,
ehcache would evict sessions without Shiro's knowledge, which would cause many problems
(e.g. "My Shiro session timeout is 30 minutes - why isn't a session available after 2 minutes?"
Answer - ehcache expired it due to the timeToIdle property set to 120 seconds.)

diskPersistent=true since we want an enterprise session management feature - ability to use sessions after
even after a JVM restart.  -->
    <cache name="shiro-activeSessionCache"
           maxElementsInMemory="10000"
           eternal="true"
           overflowToDisk="true"
           diskPersistent="true"
           diskExpiryThreadIntervalSeconds="600"/>

    <cache name="org.apache.shiro.realm.SimpleAccountRealm.authorization"
           maxElementsInMemory="100"
           eternal="false"
           timeToLiveSeconds="600"
           overflowToDisk="false"/>

</ehcache>

基本上就搭建成功了
启动的时候 有可能你会遇到 realm 找不到 很正常 因为realm 是自己定义的 注释掉 或者 自己写个realm替换掉

还有一个比较常见的错误

 org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'shiroFilter' available

这个 就很简单了
查看你的 spring-shiro 中 id名称 与web.xml 中配置的是否一致
这里写图片描述
这里写图片描述
发现还是不对?不要急是不是忘记将配置文件交由spring管理呢?
这里写图片描述

如果不想用 filter-name: shiroFilter 也可以用 targerBeanName 的value

<!--Shiro过滤器-->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>shiroFilter22</param-value>
    </init-param>
</filter>

为什么这要配置也可以呢?那下面就要介绍 DelegatingFilterProxy

猜你喜欢

转载自blog.csdn.net/Mr_yangzc/article/details/81512761