spring 整合shiro框架 模拟登录控制器。

一、导入shiro  jar包。  我在maven项目中,将常用的jar包都放在里面。

<?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.aaa</groupId>
  <artifactId>demo0807</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>demo0807 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.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.1.1.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--在这里加入依赖!  -->

    <!--spring依赖的jar-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</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-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

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


    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>


    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</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-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--数据源-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.16</version>
    </dependency>

    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>


    <!--lombok:简化实体类的编写-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.8</version>
    </dependency>


    <!--支持web-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

    <!--引入mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.1</version>
    </dependency>

    <!--处理json-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.5</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.5</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.5</version>
    </dependency>

    <!--解决Spring使用slf4j输出日志与log4j冲突的问题-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.6</version>
    </dependency>
    <!-- log4j的包 -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.6</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>

    <!--mybatis自动生成代码的jar-->
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.6</version>
    </dependency>

    <!--文件上传-->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.2</version>
    </dependency>


    <!--
        <dependency>
          <groupId>eu.bitwalker</groupId>
          <artifactId>UserAgentUtils</artifactId>
          <version>1.19</version>
        </dependency>
    -->


    <!--分页插件-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.9</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-ehcache</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.3.2</version>
    </dependency>

  </dependencies>

  <build>
    <finalName>demo0807</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>
      <!-- mybatis generator 自动生成代码插件 -->
      <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.6</version>
        <configuration>
          <!--指定配置文件的名称。默认值:${basedir}/src/main/resources/generatorConfig.xml-->
          <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
          <!--新生成的文件会覆盖原有的文件。-->
          <overwrite>true</overwrite>
          <!--如果指定该参数,执行过程会输出到控制台-->
          <verbose>true</verbose>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

二、在资源目录下创建 shiro.xml文件   我在这里 对admin目录下的文件进行拦截。

<?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">



    <!--1.安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--缓存管理器    暂时不引用他-->
        <!--<property name="cacheManager" ref="cacheManager"/>-->

        <!--会话的模式-->
        <property name="sessionMode" value="native"/>

        <!--配置realm -->
        <property name="realm" ref="myRealm"/>
    </bean>

    <!--2.缓存管理器-->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">

    </bean>


    <bean id="myRealm" class="com.aaa.realm.MyRealm">
        <property name="name" value="myRealm"/>

        <!--3.品证(密码)匹配器-->
        <!-- <property name="credentialsMatcher">
             &lt;!&ndash; The 'bootstrapDataPopulator' Sha256 hashes the password
                  (using the username as the salt) then base64 encodes it: &ndash;&gt;
             <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                 <property name="hashAlgorithmName" value="SHA-256"/>
                 &lt;!&ndash; true means hex encoded, false means base64 encoded &ndash;&gt;
                 <property name="storedCredentialsHexEncoded" value="false"/>
             </bean>
         </property>-->
    </bean>


    <!--4.shiro中的类型要交给  spring容器管理的bean-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>


    <!--5.启用注解配置-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>



    <!--  6.  shiro 的过滤器   id和名字保持一致 和web.xml 中过滤器的名字保持一致。否则配置没有效果。

    -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--1.引入安全管理器 -->
        <property name="securityManager" ref="securityManager"/>

        <!--2.登录的地址  -->
        <property name="loginUrl" value="/login.jsp"/>

        <!--3.登录成功的页面 -->
        <property name="successUrl" value="/index.jsp"/>

        <!--4.绑定一个未授权的路径。-->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>


        <!-- <property name="filters">
            <util:map>
                <entry key="aName" value-ref="someFilterPojo"/>
            </util:map>

            filterChainDefinitions  过滤器的规则声明。
            1.anon     匿名不需要验证
            2. authc 认证 需要登录
            3.perms  权限
            4.logout 注销

               /admin/** = authc    下的路径都需要进行登录认证

            从上到下  前面规定好的 冲突就是优先级。
        </property> -->
        <property name="filterChainDefinitions">
            <value>
                /login.jsp = anon
                /index.jsp = anon
                /static/** =anon
                # allow WebStart to pull the jars for the swing app:
                /*.jar = anon
                # everything else requires authentication:
                /emp/**=authc
                /admin/** = authc
            </value>
        </property>
    </bean>

</beans>

 

 

三、在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: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/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">
    <!--spring的全局配置文件-->
    <context:component-scan base-package="com.aaa"/>
    <!--加载外部资源文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password"  value="${jdbc.password}"/>
        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="5" />
        <property name="minIdle" value="10" />
        <property name="maxActive" value="20" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="2000" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="600000" />
        <property name="maxEvictableIdleTimeMillis" value="900000" />
        <property name="validationQuery" value="select 1" />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="keepAlive" value="true" />
        <property name="phyMaxUseCount" value="100000" />
        <!-- 配置监控统计拦截的filters -->
        <property name="filters" value="stat" />
    </bean>



    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--配置mybatis的映射文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.aaa.entity"/>

        <!--配置mybatis分页插件 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=mysql
                        </value>
                    </property>
                </bean>
            </array>


        </property>
        <!--如果使用mybatis的配置文件-->
        <!--<property name="configLocation" value="classpath:mybatis-config.xml"/>-->
    </bean>


    <!--扫描:dao接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.aaa.dao"/>
    </bean>



    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--事务的注解配置-->
  <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--在spring全局配置文件中 加载shiro的配置-->
    <import resource="shiro.xml"/>
</beans>

四、在web.xml文件中  添加shiro过滤器

<?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">
  <!--上下文参数-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <!--监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 配置编码方式过滤器,注意一点:要配置在所有过滤器的前面 -->
  <filter>
    <filter-name>CharacterEncodingFilter</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>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</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>
      <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>



      <!-- 拦截页面上所有发过来的请求。 1.实现模拟put 方法        -->
  <filter>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!--前端控制器
  默认加载web-inf/[servlet-name]-servlet.xml
  -->
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:mvc.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>


</web-app>

 

五、控制层  用户登录的后台管理。 realm层 MyRealm的设置。

5.1 realm 层  MyRealm

package com.aaa.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.realm.AuthenticatingRealm;
/*1.编码实现realm类
* 2.继承AuthenticatingRealm
*
* 3.返回一个实现类  验证交给shiro
*
* realm
*
* 1.获取subject传递过来的token
* 2.根据token中的用户名,找到密码
* 3.返回认证的对象。
* */
public class MyRealm extends AuthenticatingRealm {
    @Override                                           //令牌信息  从表单中传递过来的身份信息
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        //获取令牌中的用户名
        String username = usernamePasswordToken.getUsername();

        //连接数据库 进行查询操作  根据用户名 查询密码  模拟密码
        String password="666";

        //返回认证信息
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,getName());
        return info;
    }
}

 

 

 

5.2  控制层  UserController 

package com.aaa.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/user")
public class UserController {

    //获取日志对象
   private static final transient Logger log= LoggerFactory.getLogger(UserController.class);

    @RequestMapping("/login")
    public  String login(String username,String password, HttpSession session){

        Subject currentUser= SecurityUtils.getSubject();

        if (!currentUser.isAuthenticated()){
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            //记住我
//            token.setRememberMe(true);
            try {
                //调用Suject.login方法 ---》安全管理器--->认证器 ,授权器
                currentUser.login(token);
            } catch (UnknownAccountException uae) {//账号不存在
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {//密码错误
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                //密码错误 直接显示一个异常 提示用户
                throw new IncorrectCredentialsException("密码错误");
            } catch (LockedAccountException lae) {//账号锁死
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        return  "view/ok";
    }

}

 

六、过滤器的jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/8/11
  Time: 20:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录界面</title>
</head>
<body>
    <h1> 过滤器的简单测试 </h1>
    <form action="user/login" method="post">
        <div>用户名:<input type="text" name="username"> </div>
        <div>密码:<input type="text" name="password"> </div>
        <div><input type="submit" value="登录"> </div>
    </form>
</body>
</html>

 

七、  我在shiro中对admin 目录下的资源进行了过滤,需要登录验证。用户名和密码不匹配,就会抛出一个错误。

 

异常信息

 

posted @ 2019-08-12 22:29  送外卖的小菜鸟  阅读(701)  评论(0编辑  收藏  举报