Shiro 整合 Spring/SpringMVC --- Shiro(二)

Shiro 整合 Spring/SpringMVC — Shiro(二)

1. 搭建 SpringMVC 的环境

要整合 SpringMVC 就必须先搭建 SpringMVC 的环境, 这不是本文的重点, 帅帅只把配置给大家, 大家自行复制黏贴或者看看就好.

1.1 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>club.javafamily</groupId>
  <artifactId>shiro02</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>shiro02 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://localhost/shiro/</url>

  <properties>
    <springframework.version>5.2.3.RELEASE</springframework.version>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <tomcat7.port>80</tomcat7.port>
    <tomcat7.path>/shiro</tomcat7.path>
  </properties>

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

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

    <!--Spring MVC + Spring web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${springframework.version}</version>
    </dependency>

    <!-- java EE -->
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>jsp-api</artifactId>
      <version>6.0.36</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- tools -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.2.2</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.10</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.5</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>shiro02</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>

    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>${tomcat7.port}</port>
          <path>${tomcat7.path}</path>
          <uriEncoding>${project.build.sourceEncoding}</uriEncoding>
          <server>tomcat7</server>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

1.2 web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Shiro-Spring Demo</display-name>

  <!-- 定义 Spring 配置文件, 默认为 /webapp/WEB-INF/applicationContext.xml -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <!--
    配置spring核心监听器,默认会以 /WEB-INF/applicationContext.xml作为配置文件
    配合 context-param(contextConfigLocation) 加载自定义的配置文件.
  -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- SpringMVC 的 DispatcherServlet -->

  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--  自定义 springmvc 的配置文件, 默认为 /WEB-INF/dispatcher-servlet.xml    -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

1.3 dispatcher-servlet.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

   <!-- 包扫描 -->
   <context:component-scan base-package="club.javafamily.shiro"></context:component-scan>

   <!-- 视图解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/"></property>
      <property name="suffix" value=".jsp"></property>
   </bean>

   <!-- 注解驱动 -->
   <mvc:annotation-driven></mvc:annotation-driven>

   <!-- Servlet Handler 配置 DefaultServletHttpRequestHandler 将静态资源请求
    交还给 Tomcat 处理(因为 DispatchServlet 的 servlet-mapping 指定的是 / 将拦截
    所有请求, 因此 springmvc 会把静态资源请求也当成一个普通的 request 请求).
    -->
   <mvc:default-servlet-handler></mvc:default-servlet-handler>

</beans>

1.4 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
			 
</beans>

1.5 SpringMVC 环境测试

  • 添加一个 controller 用于测试 mvc 环境
package club.javafamily.shiro.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PingController {

   @GetMapping("/ping")
   public String ping() {
      return "pong";
   }
}

file

1.6 目录结构

file

2. 引入 Shiro

2.1 引入 pom 依赖

    <!--Shiro-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>${shiro.version}</version>
    </dependency>

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>${shiro.version}</version>
    </dependency>

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>${shiro.version}</version>
    </dependency>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <scope>runtime</scope>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <scope>runtime</scope>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <scope>runtime</scope>
      <version>${log4j.version}</version>
    </dependency>

2.2 配置 web.xml

在 Springmvc 环境中使用 Shiro 需要配置一个 Shiro Filter 来拦截请求.

 <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <!--
        targetFilterLifecycle 指定为 true 去
        强制调用 Filter 的 init 和 destroy 方法
      -->
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>

    <init-param>
      <param-name>targetBeanName</param-name>
      <param-value>shiroFilter2</param-value>
    </init-param>
  </filter>
	
	<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

注意 DelegatingFilterProxy 这是一个代理类, 默认情况下, 这将从 Spring IOC 容器中查找 <filter-name> 指定的 Filter Name 的 Bean 作为具体的 Filter, 也可以通过 targetBeanName 初始化参数去指定 IOC 中具体 Filter Bean 的名称(这样的设计思想是来源于 Spring Security.)

2.3 配置 Shiro 组件

applicationContext.xml 中配置 Shiro 的核心组件

 <!-- 配置 SecurityManager  -->
   <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
      <property name="cacheManager" ref="cacheManager"></property>
      <property name="realm" ref="shiroRealm"></property>
   </bean>

   <!-- 使用 EhCache 作为 Shiro 缓存  -->
   <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
      <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
   </bean>

   <!-- 配置 Realm, 现在只是一个实现了 Realm 接口的空实现  -->
   <bean id="shiroRealm" class="club.javafamily.shiro.realm.ShiroRealm"></bean>

   <!--
      定义 Shiro BeanPostProcess 来自动调用实现了 {@link org.apache.shiro.util.Initializable}
      或者 {@link org.apache.shiro.util.Destroyable} 接口的 init 和 destroy 方法
      需要注意的是: LifecycleBeanPostProcessor 并不能确定 init 和 destroy 方法是否已经
      被调用, 因此当配置了这个 BeanPostProcess 之后不要手动调用 init 和 destroy 方法,
      也不要再配置 spring 的 init-method 和 destroy-method 属性
    -->
   <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>

   <!-- 启用 IOC 容器中使用 Shiro 的注解, 但是必须在配置了 lifecycleBeanPostProcessor 之后,
     因为 DefaultAdvisorAutoProxyCreator 会扫描上下文(因为 DefaultAdvisorAutoProxyCreator
     也是一个 BeanPostProcess ), 寻找所有的 Advisor 并应用到所有符合切点的 Bean.
     -->
   <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
      depends-on="lifecycleBeanPostProcessor"></bean>

   <!-- 
		  配置 Shiro Filter
     -->
   <bean id="shiroFilter2" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
      <property name="securityManager" ref="securityManager"></property>
      <property name="loginUrl" value="/login.jsp"></property>
      <property name="successUrl" value="/index.jsp"></property>
      <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"></property>

      <!--   
			指定拦截规则, 除了 login.jsp 和 /ping 请求外都需要认证后才可以访问.
         -->
      <property name="filterChainDefinitions">
         <value>
            /login.jsp = anon
            /ping = anon
            /** = authc
         </value>
      </property>
   </bean>
2.3.1 ShiroFilter

上面配置的 Shiro Filter 的 id 必须和 web.xml 文件中配置的 DelegatingFilterProxy 的 targetBeanName 一致, 如果没有指定 targetBeanName 则默认为 <filter-name> 指定的 filter 名称. 如果不一致则会抛出以下异常, 因为 web.xml 配置的是 Filter 代理

严重: Exception starting filter shiroFilter
         org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'shiroFilter' available
2.3.2 filterChainDefinitions

ShiroFilterfilterChainDefinitions 指定那些页面需要受保护, 以及访问这些页面那些权限

  • anon: 代表可以被匿名访问(不配置也代表可以匿名访问, 但是需要注意 /** 是配置所有的请求)
  • authc: 代表必须认证登录后才能访问
  • /** 代表所有请求

filterChainDefinitions 采用第一次匹配优先的方式. 并支持通配符匹配

  • ?: 匹配一个任意字符
  • *: 匹配 0 个或者多个任意字符
  • **: 匹配多层路径
2.3.3 jsp 页面
  • index.jsp 默认的项目首页, 也是我们通过 ShirosuccessUrl 配置的登录成功跳转的页面.
  • list.jsp 需要授权的页面
  • login.jsp 登录页面
  • unauthorizedUrl.jsp 没有权限跳转的提示页面
2.3.4 ShiroRealm

上面的 ShiroRealm 目前我们只是一个实现了 Reaml 接口的空实现, 关于 Reaml 的作用可以参考我们上一篇 Shiro 文章 认证与授权 — Shiro (一)

package club.javafamily.shiro.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.realm.Realm;

public class ShiroRealm implements Realm {
   @Override
   public String getName() {
      return null;
   }

   @Override
   public boolean supports(AuthenticationToken token) {
      return false;
   }

   @Override
   public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
      return null;
   }
}

2.4 ehcache.xml

因为我们 shiro-cache 使用了 ehcache, 所以需要添加 ehcache 的配置, 不多说, 不懂得.

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
         updateCheck="true" monitoring="autodetect" dynamicConfig="true">
   <defaultCache
      eternal="false"
      maxElementsInMemory="1000"
      overflowToDisk="false"
      diskPersistent="false"
      timeToIdleSeconds="0"
      timeToLiveSeconds="600"
      memoryStoreEvictionPolicy="LRU" />
</ehcache>

2.5 log4j.properties

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n

# General Apache libraries
log4j.logger.org.apache=WARN

# Spring
log4j.logger.org.springframework=WARN

# Default Shiro logging
log4j.logger.org.apache.shiro=INFO

# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

2.6 运行测试

因为我们引入了 tomcat7-maven-plugin 所以只需要执行 mvn tomcat7:run 来发布运行项目就可以进行测试.

  • 访问 http://localhost/shiro/ping 或者 http://localhost/shiro/login.jsp 都可以直接访问

file

  • 访问 http://localhost/shiro/list.jsp 或者任何不存在的路径将都会自动跳转到登录界面.

file

诺, 源码传送门:

file

具体的登录认证我们下一篇再聊哦…

file

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值