shiro_02_身份认证加密

目录

一、盐加密

1.明文密码 

 2.md5加密

3.md5加盐加密 

4.md5加盐加密加次数  1024

5.演示代码

二、shiro的认证 

1.完成登录的方法 Mapper层的编写和biz层 

2.自定义realm(重点)  

3.Spring与shiro的整合(注意)

4.测试


一、盐加密

 数据库密码的发展史
    第一个阶段:明文密码    123456
    第二个阶段:md5加密    e10adc3949ba59abbe56e057f20f883e
    第三个阶段:md5加盐加密
    第四个阶段:md5加盐加密加次数         1024

1.明文密码 

也就是说在数据库里密码是可以看到的 

 

 2.md5加密

数据库里的密码已经加密了 

也就相当于密码是 e10adc3949ba59abbe56e057f20f883e=123456

还可以看下面这张图也就是说这个加密还不够完全,它可以解出来,而且这个加密的密还是同一个,它始终不会变的e10adc3949ba59abbe56e057f20f883e 

3.md5加盐加密 

123456:原始密码
盐:1
e10adc3949ba59abbe56e057f20f883f
盐:2
e10adc3949ba59abbe56e057f20f883g 

就是看你的盐加了多少然后就在继续加密

4.md5加盐加密加次数  1024

 你要知道加了多少盐,还要知道多少次,也就是说别人加密多少次,你就要解密多少次

5.演示代码

1.导入pom依赖

<!--    shiro相关依赖-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
</dependency>

所有的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>org.example</groupId>
  <artifactId>ssm</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>ssm Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

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

    <!--添加jar包依赖-->
    <!--1.spring 5.0.2.RELEASE相关-->
    <spring.version>5.0.2.RELEASE</spring.version>
    <!--2.mybatis相关-->
    <mybatis.version>3.4.5</mybatis.version>
    <!--mysql-->
    <mysql.version>5.1.44</mysql.version>
    <!--pagehelper分页jar依赖-->
    <pagehelper.version>5.1.2</pagehelper.version>
    <!--mybatis与spring集成jar依赖-->
    <mybatis.spring.version>1.3.1</mybatis.spring.version>
    <!--3.dbcp2连接池相关 druid-->
    <commons.dbcp2.version>2.1.1</commons.dbcp2.version>
    <commons.pool2.version>2.4.3</commons.pool2.version>
    <!--4.log日志相关-->
    <log4j2.version>2.9.1</log4j2.version>
    <!--5.其他-->
    <junit.version>4.12</junit.version>
    <servlet.version>4.0.0</servlet.version>
    <lombok.version>1.18.2</lombok.version>
  </properties>

  <dependencies>
    <!--1.spring相关-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <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>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--2.mybatis相关-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <!--mysql-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <!--pagehelper分页插件jar包依赖-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>${pagehelper.version}</version>
    </dependency>
    <!--mybatis与spring集成jar包依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis.spring.version}</version>
    </dependency>

    <!--3.dbcp2连接池相关-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>${commons.dbcp2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>${commons.pool2.version}</version>
    </dependency>

    <!--4.log日志相关依赖-->
    <!--核心log4j2jar包-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <!--web工程需要包含log4j-web,非web工程不需要-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-web</artifactId>
      <version>${log4j2.version}</version>
    </dependency>

    <!--5.其他-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- jsp依赖-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>

    <!--做服务端参数校验   JSR303 的jar包依赖-->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.7.Final</version>
    </dependency>

    <!--    用来SpringMVC支持json数据转换-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.3</version>
    </dependency>

<!--    shiro相关依赖-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.3.2</version>
    </dependency>

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.3.2</version>
    </dependency>

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>ssm</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>jdbc.properties</include>
          <include>*.xml</include>
        </includes>
      </resource>
    </resources>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <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>${project.build.sourceEncoding}</encoding>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-maven-plugin</artifactId>
          <version>1.3.2</version>
          <dependencies>
            <!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 -->
            <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>${mysql.version}</version>
            </dependency>
          </dependencies>
          <configuration>
            <overwrite>true</overwrite>
          </configuration>
        </plugin>
        <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>
  </build>
</project>

2.配置 web.xml  交给spring进行管理

<!-- shiro过滤器定义 -->
<filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
    <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>

所有web.xml

<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>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <!-- 读取Spring上下文的监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Spring MVC servlet -->
  <servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--此参数可以不配置,默认值为:/WEB-INF/springmvc-servlet.xml-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/springmvc-servlet.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>

  <!-- 中文乱码处理 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- shiro过滤器定义 -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
      <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>

</web-app>

4.在这里新建一个包,里面放PasswordHelper.java

package com.jwj.shiro;


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次
     * 加密1024次,解密也是1024次
     */
    private static final int hashIterations = 1024;

    /**
     * true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储
     * 你是不是base64位的进行存储
     */
    private static final boolean storedCredentialsHexEncoded = true;

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

    /**
     * 获得加密后的凭证
     *  生成一个秘密
     * @param credentials 凭证(即密码)
     * @param salt        盐
     * @return
     * 原始密码 + 盐  =  加密后的  返回值String就是加密后的
     */
    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("123456", salt);
        System.out.println(credentials);
//        加密后的长度
        System.out.println(credentials.length());
//        拿到加密后的密码和原始化的密码如果为true,就代码加密成功了
        boolean b = checkCredentials("123456", salt, credentials);
        System.out.println(b);
    }
}

运行一下如图所示:
 

123456 原始密码
76925b1ed64ebf33185454c9da646394    盐
32
fc3a986b62b7c6710e9ee7cf26b5d917    加密后
32
true 

拿到原始密码和盐以及加密后的密码做对比如果为true说明加密成功

我们在运行一次看看这两者之间是不是一样的如图所示:

可以看到明显的不一样了,盐不一样了也就会导致加密后的也不一样了

如果说你有一万数据被泄露了,它要解密这些东西,它首先要拿到加密的次数(1024),要解密也的逐条进解密,因为我们每个加的盐都是不一样的。

我们怎么拿到数据库里的数据

我们查询的SQL语句也不一样了

之前的SQL语句查询

select * from t_oa_user where username='zs' and password=123456

现在的SQL语句查询

select * from t_oa_user where username='zs'

假设:用户名:zhangsan   密码:zhangsan

传递到后台 就能接收到这两个变量

1.生成随机的盐

2.利用 zhangsan 原始密码 + 生成的盐 = 得到加密后的密码

3. 在执行 insert 语句

二、shiro的认证 

1.完成登录的方法 Mapper层的编写,接着就是biz层

2.完成自定义realm(重点)

3.Spring与shiro的整合(注意)

4.测试

1.完成登录的方法 Mapper层的编写和biz层 

 通过逆向工程将五张表生成对应的model、Mapper

generatorConfig.xml        主要生成好了之后记得要把它切换掉为其他的

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
       "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<!-- 引入配置文件 -->
<properties resource="jdbc.properties"/>

<!--指定数据库jdbc驱动jar包的位置-->
<classPathEntry location="F:\\Courseware\\SoftwareInstallPath\\maven\\apache-maven-3.5.0-bin\\apache-maven-3.5.0-bin\\mvn_repository\\mysql\\mysql-connector-java\\5.1.44\\mysql-connector-java-5.1.44.jar"/>

<!-- 一个数据库一个context -->
<context id="infoGuardian">
    <!-- 注释 -->
    <commentGenerator>
        <property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
        <property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳 -->
    </commentGenerator>

    <!-- jdbc连接 -->
    <jdbcConnection driverClass="${jdbc.driver}"
                    connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>

    <!-- 类型转换 -->
    <javaTypeResolver>
        <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
        <property name="forceBigDecimals" value="false"/>
    </javaTypeResolver>

    <!-- 01 指定javaBean生成的位置 -->
    <!-- targetPackage:指定生成的model生成所在的包名 -->
    <!-- targetProject:指定在该项目下所在的路径  -->
    <javaModelGenerator targetPackage="com.jwj.ssm.model"
                        targetProject="src/main/java">
        <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
        <property name="enableSubPackages" value="false"/>
        <!-- 是否对model添加构造函数 -->
        <property name="constructorBased" value="true"/>
        <!-- 是否针对string类型的字段在set的时候进行trim调用 -->
        <property name="trimStrings" value="false"/>
        <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
        <property name="immutable" value="false"/>
    </javaModelGenerator>

    <!-- 02 指定sql映射文件生成的位置 -->
    <sqlMapGenerator targetPackage="com.jwj.ssm.mapper"
                     targetProject="src/main/java">
        <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
        <property name="enableSubPackages" value="false"/>
    </sqlMapGenerator>

    <!-- 03 生成XxxMapper接口 -->
    <!-- type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象 -->
    <!-- type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象 -->
    <!-- type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
    <javaClientGenerator targetPackage="com.jwj.ssm.mapper"
                         targetProject="src/main/java" type="XMLMAPPER">
        <!-- 是否在当前路径下新加一层schema,false路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
        <property name="enableSubPackages" value="false"/>
    </javaClientGenerator>

    <!-- 配置表信息 -->
    <!-- schema即为数据库名 -->
    <!-- tableName为对应的数据库表 -->
    <!-- domainObjectName是要生成的实体类 -->
    <!-- enable*ByExample是否生成 example类 -->
    <!--<table schema="" tableName="t_book" domainObjectName="Book"-->
    <!--enableCountByExample="false" enableDeleteByExample="false"-->
    <!--enableSelectByExample="false" enableUpdateByExample="false">-->
    <!--&lt;!&ndash; 忽略列,不生成bean 字段 &ndash;&gt;-->
    <!--&lt;!&ndash; <ignoreColumn column="FRED" /> &ndash;&gt;-->
    <!--&lt;!&ndash; 指定列的java数据类型 &ndash;&gt;-->
    <!--&lt;!&ndash; <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> &ndash;&gt;-->
    <!--</table>-->

    <table schema="" tableName="t_shiro_user" domainObjectName="User"
           enableCountByExample="false" enableDeleteByExample="false"
           enableSelectByExample="false" enableUpdateByExample="false">
    </table>

    <table schema="" tableName="t_shiro_role" domainObjectName="Role"
           enableCountByExample="false" enableDeleteByExample="false"
           enableSelectByExample="false" enableUpdateByExample="false">
    </table>

    <table schema="" tableName="t_shiro_permission" domainObjectName="Permission"
           enableCountByExample="false" enableDeleteByExample="false"
           enableSelectByExample="false" enableUpdateByExample="false">
    </table>

    <table schema="" tableName="t_shiro_user_role" domainObjectName="UserRole"
           enableCountByExample="false" enableDeleteByExample="false"
           enableSelectByExample="false" enableUpdateByExample="false">
    </table>

    <table schema="" tableName="t_shiro_role_permission" domainObjectName="RolePermission"
           enableCountByExample="false" enableDeleteByExample="false"
           enableSelectByExample="false" enableUpdateByExample="false">
    </table>

</context>
</generatorConfiguration>

我们这就生成好了如图所示:​​​​​​​​​​​​​​ 

在我们的UserMapper.xml中 新增方法

<!--  通过用户名进行查询-->
  <select id="queryUserByUserName" resultType="com.jwj.ssm.model.User" parameterType="java.lang.String" >
    select
    <include refid="Base_Column_List" />
    from t_shiro_user
    where userName = #{userName}
  </select>

UserMapper.java 也加上 我们刚刚写的方法

package com.jwj.ssm.mapper;

import com.jwj.ssm.model.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

//这个加也可以不加也可以,不加那边的实现方法就会报红,会感觉不舒服,加了就不会报红
@Repository
public interface UserMapper {
    int deleteByPrimaryKey(Integer userid);

    int insert(User record);

    int insertSelective(User record);

    User selectByPrimaryKey(Integer userid);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);

    User queryUserByUserName(@Param("userName") String userName);
}

UserBiz.java

package com.jwj.ssm.biz;

import com.jwj.ssm.model.User;
import org.apache.ibatis.annotations.Param;

/**
 * @author 敢敢
 * @site www.javajwj.com
 * @company xxx公司
 * @create  2022-08-25 19:10
 */
public interface UserBiz {
    int deleteByPrimaryKey(Integer userid);

    int insert(User record);

    int insertSelective(User record);

    User selectByPrimaryKey(Integer userid);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);

    User queryUserByUserName(String userName);
}

实现类 UserBizImp.java

package com.jwj.ssm.biz.impl;

import com.jwj.ssm.biz.UserBiz;
import com.jwj.ssm.mapper.UserMapper;
import com.jwj.ssm.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 敢敢
 * @site www.javajwj.com
 * @company xxx公司
 * @create  2022-08-25 19:11
 */
@Service("userBiz")
public class UserBizImpl implements UserBiz {
    @Autowired
    private UserMapper userMapper;

    @Override
    public int deleteByPrimaryKey(Integer userid) {
        return userMapper.deleteByPrimaryKey(userid);
    }

    @Override
    public int insert(User record) {
        return userMapper.insert(record);
    }

    @Override
    public int insertSelective(User record) {
        return userMapper.insertSelective(record);
    }

    @Override
    public User selectByPrimaryKey(Integer userid) {
        return userMapper.selectByPrimaryKey(userid);
    }

    @Override
    public int updateByPrimaryKeySelective(User record) {
        return userMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(User record) {
        return userMapper.updateByPrimaryKey(record);
    }

    @Override
    public User queryUserByUserName(String userName) {
        return userMapper.queryUserByUserName(userName);
    }
}

2.自定义realm(重点)  

MyRealm.java

package com.jwj.ssm.shiro;

import com.jwj.ssm.biz.UserBiz;
import com.jwj.ssm.model.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
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;

/**
 * @author 敢敢
 * @site www.javajwj.com
 * @company xxx公司
 * @create  2022-08-25 19:19
 */
public class MyRealm extends AuthorizingRealm {
    public UserBiz userBiz;

    public UserBiz getUserBiz() {
        return userBiz;
    }

    public void setUserBiz(UserBiz userBiz) {
        this.userBiz = userBiz;
    }

    /**
     * 授权
     * @param principalCollection
     * @return
     *  shiro-web.ini
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     *  shiro.ini
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        拿到我们的用户名
        String userName = authenticationToken.getPrincipal().toString();
        User user = userBiz.queryUserByUserName(userName);
//       拿到数据库中的用户信息,放入token凭证中,用于controler进行对比
        AuthenticationInfo info = new SimpleAuthenticationInfo(
                user.getUsername(),
                user.getPassword(),
                ByteSource.Util.bytes(user.getSalt()),
                this.getName() //realm的名字
        );
        return info;
    }
}

交给我们的spring进行管理

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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
               xmlns:aop="http://www.springframework.org/schema/aop"
               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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--随着后续,框架会越学越多,不能讲所有的框架配置,放到同一个配置文件,否则不便于管理-->
    <import resource="applicationContext-mybatis.xml"></import>
    <import resource="applicationContext-shiro.xml"></import>

</beans>

3.Spring与shiro的整合(注意)

 ①shiro 在加载的时候,Spring上下文还没有加载完毕,所以@component与@autowised是不能使用的

② spring-shiro.xml 文件中,Myream需要依赖的业务类,由于没有被Spring配置,所以需要指定bean的id 通过@Service("具体的名字")

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

<!--  第一种方式  <bean class="com.jwj.ssm.biz.impl.UserBizImpl" id="userBiz"></bean>-->
    <!--配置自定义的Realm-->
    <bean id="shiroRealm" class="com.jwj.ssm.shiro.MyRealm">
        <property name="userBiz" ref="userBiz" />
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
        <property name="credentialsMatcher">
            <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <!--指定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>
        </property>
    </bean>

    <!--注册安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroRealm" />
    </bean>

    <!--Shiro核心过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager" />
        <!-- 身份验证失败,跳转到登录页面 -->
        <property name="loginUrl" value="/login"/>
        <!-- 身份验证成功,跳转到指定页面 -->
        <!--<property name="successUrl" value="/index.jsp"/>-->
        <!-- 权限验证失败,跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                <!--
                注:anon,authcBasic,auchc,user是认证过滤器
                    perms,roles,ssl,rest,port是授权过滤器
                -->
                <!--anon 表示匿名访问,不需要认证以及授权-->
                <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
                <!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->
                /user/login=anon
                /user/updatePwd.jsp=authc
                /admin/*.jsp=roles[admin]
                /user/teacher.jsp=perms["user:update"]
                <!-- /css/**               = anon
                 /images/**            = anon
                 /js/**                = anon
                 /                     = anon
                 /user/logout          = logout
                 /user/**              = anon
                 /userInfo/**          = authc
                 /dict/**              = authc
                 /console/**           = roles[admin]
                 /**                   = anon-->
            </value>
        </property>
    </bean>

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

LoginController.java

package com.jwj.ssm.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

/**
 * @author 敢敢
 * @site www.javajwj.com
 * @company xxx公司
 * @create  2022-08-20 12:12
 */
@Controller
public class LoginController {

//    @RequestMapping("/login")
//    public String login(HttpServletRequest request){
        登录成功一般需要 保存 用户信息
//        String uname = request.getParameter("uname");
//        if("zhangsan".equals(uname)){
//            request.getSession().setAttribute("uname",uname);
//        }
//        return "index";
//    }
//
//    @RequestMapping("/logout")
//    public String logout(HttpServletRequest request){
        做销毁
//        request.getSession().invalidate();
//        return "index";
//    }


    @RequestMapping("/login")
    public String login(HttpServletRequest request){
        try {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
//          生成令牌
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//            生成主体
            Subject subject = SecurityUtils.getSubject();
//            拿到令牌进行登录
            subject.login(token);
            return "main";
        }catch (Exception e){
            request.setAttribute("message","账户密码错误...");
            return "login";
        }
    }

    @RequestMapping("/logout")
    public String logout(HttpServletRequest request){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
}

4.测试

 把这个复制到我们的webapp下面

运行结果它也就那到了我们的用户名和盐以及加密如图所示:

最终运行结果如图所示:

结论:doGetAuthenticationInfo认证方法是web层执行subject.login 方法触发的。

 三、总结

1.盐加密 

1.明文密码

2.md5 加密      密文密码

3.md5 加盐加密          一个明文对应多个密文

4.md5 加盐加密加次数

2.shiro 的认证 

1.Mapper层        ——        通过账户名获取用户信息

2.将用户信息给MyRealm 认证方法,认证的过程交给安全管理器

3.MyRealm的配置,配置spring-shiro.xml 文件中

        ① shiro接管MyRealm的时候,还没有被Spring所接管导致@component与@autowised用不了

        ② 采用配置的形式配置UserBiz,需要给@service指定bean的名称

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值