Shiro认证

Shiro用户认证

      • 一. 导入相关依赖
      • 二. 自定义Realm
      • 三. 配置spring-shiro.xml文件
      • 四. 修改web.xml文件,添加shiroFilter的配置
      • 五. 用户注册案例

一. 导入相关依赖

完整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>com.zking</groupId>
  <artifactId>shiro</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>shiro Maven Webapp</name>
  <url>http://www.example.com</url>

  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
    <maven.compiler.source>1.8</maven.compiler.source>

    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.encoding>utf8</maven.compiler.encoding>
    <mybatis-generator-maven-plugin.version>1.3.2</mybatis-generator-maven-plugin.version>

    <junit.version>4.12</junit.version>
    <servlet.version>4.0.0</servlet.version>
    <spring.version>5.0.2.RELEASE</spring.version>

    <jackson.version>2.9.3</jackson.version>
    <hibernate-validator.version>6.0.7.Final</hibernate-validator.version>
    <jstl.version>1.2</jstl.version>

    <standard.version>1.1.2</standard.version>
    <commons-fileupload.version>1.3.3</commons-fileupload.version>
    <mybatis.version>3.4.5</mybatis.version>

    <pagehelper.version>5.1.2</pagehelper.version>
    <mybatis-spring.version>1.3.1</mybatis-spring.version>
    <mybatis-ehcache.version>1.1.0</mybatis-ehcache.version>

    <!--<ehcache.version>2.10.0</ehcache.version>-->
    <mysql.driver.version>5.1.44</mysql.driver.version>
    <commons-dbcp2.version>2.1.1</commons-dbcp2.version>
    <commons-pool2.version>2.4.3</commons-pool2.version>

    <slf4j.version>1.7.7</slf4j.version>
    <log4j2.version>2.9.1</log4j2.version>
    <disruptor.version>3.2.0</disruptor.version>

    <shiro.version>1.2.5</shiro.version>
  </properties>

  <build>
    <finalName>shiro</finalName>
    <resources>
      <!--解决mybatis-generator-maven-plugin运行时没有将XxxMapper.xml文件放入target文件夹的问题-->
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <!--解决mybatis-generator-maven-plugin运行时没有将jdbc.properites文件放入target文件夹的问题-->
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>*.ini</include>
          <include>*.properties</include>
          <include>*.xml</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <!-- 编码和编译和JDK版本 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <encoding>${maven.compiler.encoding}</encoding>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>${mybatis-generator-maven-plugin.version}</version>
        <dependencies>
          <!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 -->
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.driver.version}</version>
          </dependency>
        </dependencies>
        <configuration>
          <overwrite>true</overwrite>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <!-- ********************** junit单元测试依赖 ********************** -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- ********************** Java Servlet API  ********************** -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>

    <!-- ********************** spring依赖 ********************** -->
    <!--1)spring核心依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring ioc依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring 扩展依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--2)spring dao层依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--3)aop相关依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--4)spring web相关依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--5) spring test相关依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--6)springMVC框架-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--7)spring对ehcache的相关支持-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--8)jackson相关依赖-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>jackson-annotations</artifactId>
          <groupId>com.fasterxml.jackson.core</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <!--9) JSR 303服务器验证 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>${hibernate-validator.version}</version>
    </dependency>
    <!--10) JSTL依赖 -->
    <!-- 缺少下面的这两个jar包会报java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config -->
    <!-- 原因:org.springframework.web.servlet.view.JstlView在视图解析时需要这二个jar包-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>${standard.version}</version>
    </dependency>
    <!--11) 文件上传相关依赖 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>${commons-fileupload.version}</version>
    </dependency>

    <!-- ********************** Mybatis依赖 ********************** -->
    <!--1) mybatis核心 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <!--2) Mybatis分页插件-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>${pagehelper.version}</version>
    </dependency>
    <!--3) spring整合mybatis与spring整合 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis-spring.version}</version>
    </dependency>
    <!--4) mybatis与ehcache整合 -->
    <dependency>
      <groupId>org.mybatis.caches</groupId>
      <artifactId>mybatis-ehcache</artifactId>
      <version>${mybatis-ehcache.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
      </exclusions>
    </dependency>

    <!-- ********************** ehcache依赖 ********************** -->
    <!--mybatis-ehcache已导入-->
    <!--<dependency>-->
    <!--<groupId>net.sf.ehcache</groupId>-->
    <!--<artifactId>ehcache</artifactId>-->
    <!--<version>${ehcache.version}</version>-->
    <!--</dependency>-->

    <!-- ********************** Mysql JDBC驱动 ********************** -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.driver.version}</version>
    </dependency>

    <!-- ********************** dbcp2连接池依赖 ********************** -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>${commons-dbcp2.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>commons-pool2</artifactId>
          <groupId>org.apache.commons</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>${commons-pool2.version}</version>
    </dependency>

    <!-- **********************  日志配置  ********************** -->
    <!--记得修改mybatis.cfg.xml添加如下内容-->
    <!--<setting name="logImpl" value="SLF4J"/>-->
    <!-- log配置:Slf4j+Log4j2  -->
    <!--1) slf4j核心包-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>${slf4j.version}</version>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <!--2) 用于与slf4j保持桥接-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <version>${log4j2.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <!--3) 核心log4j2jar包-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <!--4) web工程需要包含log4j-web,非web工程不需要-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-web</artifactId>
      <version>${log4j2.version}</version>
      <scope>runtime</scope>
    </dependency>
    <!--5) 需要使用log4j2的AsyncLogger需要包含disruptor-->
    <dependency>
      <groupId>com.lmax</groupId>
      <artifactId>disruptor</artifactId>
      <version>${disruptor.version}</version>
    </dependency>

    <!-- **********************  shiro配置  ********************** -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>${shiro.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>${shiro.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>ehcache-core</artifactId>
          <groupId>net.sf.ehcache</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <!--shiro end-->

  </dependencies>


</project>
  1. 工具类

PasswordHelper:

   package com.zking.shiro.shiros;


import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;

/**
 * 用于shiro权限认证的密码工具类
 */
public class PasswordHelper {

    /**
     * 随机数生成器
     */
    private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();

    /**
     * 指定hash算法为MD5
     */
    private static final String hashAlgorithmName = "md5";

    /**
     * 指定散列次数为1024次,即加密1024
     */
    private static final int hashIterations = 1024;

    /**
     * true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储
     */
    private static final boolean storedCredentialsHexEncoded = true;

    /**
     * 获得加密用的盐
     *
     * @return
     */
    public static String createSalt() {
        return randomNumberGenerator.nextBytes().toHex();
    }

    /**
     * 获得加密后的凭证
     *
     * @param credentials 凭证(即密码)
     * @param salt        
     * @return
     */
    public static String createCredentials(String credentials, String salt) {
        SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,
                salt, hashIterations);
        return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();
    }


    /**
     * 进行密码验证
     *
     * @param credentials        未加密的密码
     * @param salt               
     * @param encryptCredentials 加密后的密码
     * @return
     */
    public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {
        return encryptCredentials.equals(createCredentials(credentials, salt));
    }

    public static void main(String[] args) {
        String salt = createSalt();
        System.out.println(salt);
        System.out.println(salt.length());
        //String credentials = createCredentials("888888", salt);
        //System.out.println(credentials);
        //System.out.println(credentials.length());
    }
}
 注:spring中关于shiro的配置要与工具类中的配置一致
     算法+散列次数+(Hex存储|Base64-encoded存储)

二. 自定义Realm

UserRealm:

    package com.zking.shiro.shiros;

import com.zking.shiro.model.User;
import com.zking.shiro.service.IUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * 自定义Realm
 */

public class UserRealm extends AuthorizingRealm {

    private static final Integer LOCKED = new Integer(1);

    //用户对应的角色信息与权限信息都保存在数据库中,通过IUserService获取数据
    @Autowired
    private IUserService userService;

    public UserRealm() {
    }

    public UserRealm(CacheManager cacheManager) {
        super(cacheManager);
    }

    public UserRealm(CredentialsMatcher matcher) {
        super(matcher);
    }

    public UserRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    /**
     * 返回一个唯一的Realm名字
     *
     * @return
     */
    @Override
    public String getName() {
        return "UserRealm";//WeixinRealm,QqRealm
    }

    /**
     * 判断此Realm是否支持此Token
     *
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;//仅支持UsernamePasswordToken类型的Token
    }

    /**
     * 提供用户信息返回授权信息
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //查询用户已授予的角色及权限
        String username = (String) principalCollection.getPrimaryPrincipal();
        User user = new User();
        user.setUsername(username);
        Set<String> permissions = userService.listPermissionsByUserName(user);
        Set<String> roles = userService.listRolesByUserName(user);

        //返回授权信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);//
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 提供用户信息返回认证信息(此时未进行密码比较)
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //查询用户已授予的角色及权限
        String username = (String) authenticationToken.getPrincipal();
        User user = new User();
        user.setUsername(username);
        User u = userService.loadByUsername(user);

        if (null == u) {
            throw new UnknownAccountException();//帐号不存在
        }
        if (LOCKED.equals(u.getLocked())) {
            throw new LockedAccountException(); //帐号已锁定
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以在此判断或自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                u.getUsername(),
                u.getPassword(),
                ByteSource.Util.bytes(u.getSalt()),
                getName()
        );
        return authenticationInfo;
    }
}

三. 配置spring-shiro.xml文件

日常报错:
Shiro认证_第1张图片
解决:
Shiro认证_第2张图片
在这里插入图片描述
spring-shiro.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    <description>apache shiro配置</description>

    <!-- 缓存管理器:本章使用Ehcache实现,也可以换成redis等其它缓存技术 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
    </bean>

    <!-- 凭证匹配器 -->
    <bean id="credentialsMatcher" class="com.hjj.shiro.shiros.RetryLimitHashedCredentialsMatcher" init-method="init">
        <!--使用有参数构造方法创建对象,注入缓存管理器-->
        <constructor-arg ref="cacheManager"/>

        <!--指定缓存对象的名字-->
        <property name="cacheName" value="passwordRetryCache"/>

        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
        <!--指定hash算法为MD5-->
        <property name="hashAlgorithmName" value="md5"/>
        <!--指定散列次数为1024次-->
        <property name="hashIterations" value="1024"/>
        <!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
        <property name="storedCredentialsHexEncoded" value="true"/>
    </bean>

    <!-- Realm实现 -->
    <bean id="userRealm" class="com.hjj.shiro.shiros.UserRealm">
        <property name="userService" ref="IUserService"/>
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

        <property name="realm" ref="userRealm"/>
    </bean>

    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

        <property name="securityManager" ref="securityManager"/>

        <!--访问需要认证的地址时,没有认证跳转的地址,默认跳网站首页,然后经springmvc转到/WEB-INF/jsp/login.jsp-->
        <property name="loginUrl" value="/"/>

        <!-- 登录后,没有访问权限将跳转的地址 -->
        <property name="unauthorizedUrl" value="/user/unauthorized"/>

        <property name="filterChainDefinitions">
            <!-- **表示匹配0个或多个路径 ,*表示匹配0个或多个字符串,?表示匹配一个字符 -->
            <value>
                /css/**               = anon
                /images/**            = anon
                /js/**                = anon
                /                     = anon
                /user/logout          = logout
                /user/**              = anon
                /userInfo/**          = authc
                /dict/**              = authc
                /console/**           = roles[admin]
                /sys/**               = authc
                /**                   = anon
            </value>
        </property>
    </bean>

    <!-- Shiro生命周期处理器-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

</beans>

四. 修改web.xml文件,添加shiroFilter的配置

注:使用的代理类DelegatingFilterProxy
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">
  <display-name>Archetype Created Web Application</display-name>
  <!--1. Spring和web项目集成 -->
  <context-param>
    <!--1) spring上下文配置文件 -->
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
  </context-param>
  <listener>
    <!--2) 读取Spring上下文的监听器 -->
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <!--3) 防止Spring内存溢出监听器 -->
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  </listener>

  <!--2. 中文乱码处理 -->
  <filter>
    <filter-name>EncodingFiter</filter-name>
    <filter-class>com.zking.shiro.util.EncodingFiter</filter-class>
    <!--web.xml 3.0的新特性,是否支持异步-->
    <async-supported>true</async-supported>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>EncodingFiter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--3. SpringMVC中央控制器 -->
  <servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <!--web.xml 3.0的新特性,是否支持异步-->
    <async-supported>true</async-supported>
  </servlet>
  <servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--4. shiro配置开始 -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <!--DelegatingFilterProxy作用是自动到spring容器查找名为shiroFilter(filter-name)的bean并把所有Filter的操作委托给它-->
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
    <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>
  </filter-mapping>
  <!-- shiro配置 结束 -->

  <welcome-file-list>
    <welcome-file>/user/index.shtml</welcome-file>
  </welcome-file-list>
</web-app>

五. 用户注册案例

md5+盐生成新的凭证
保存新凭证+盐到数据
Shiro认证_第3张图片
Shiro认证_第4张图片
Shiro认证_第5张图片
7. 用户登陆
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);//PhoneToken
UnknownAccountException
LockedAccountException
IncorrectCredentialsException:捕获密码错误异常
ExcessiveAttemptsException:捕获错误登录过多的异常

登陆成功后将user保存至shiro的会话中,已备之后使用

你可能感兴趣的:(Shiro)