zoukankan      html  css  js  c++  java
  • shiro+SSM

    权限概述

    什么是权限管理

    权限管理实现对用户访问系统的控制
    用户可以访问而且只能访问自己被授权的资源
    只要有用户和密码的系统,权限管理几乎都会出现

    举例
    给张三赋予“人力资源经理”角色,
    “人力资源经理”具有“查询员工”、“添加员工”、“修改员工”和“删除员工”权限。
    此时张三能够进入系统,则可以进行这些操作;

    权限管理

    1. 认证
      对于需要访问控制的资源用户首先经过身份认证
      判断一个用户是否为合法用户的处理过程
    2. 授权
      认证通过后用户具有资源的访问权限-方可访问
      控制能够访问哪些资源

    shiro概述

    Apache Shiro是Java的一个安全框架
    Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证、授权、加密、会话管理、与Web集成、缓存等
    Shiro使用起来小而简单
    spring中有spring security ,是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。
    shiro不依赖于spring,shiro不仅可以实现web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,
    shiro属于轻量框架,越来越多企业项目开始使用shiro.

    shiro核心概念

    核心类

    整体类图
    在这里插入图片描述

    1. Authentication
      身份认证/登录,验证用户是不是拥有相应的身份;
    2. Authorization
      授权,即权限验证,验证某个已认证的用户是否拥有某个权限;
    3. Session Manager
      会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
    4. Cryptography
      加密,保护数据的安全性
    5. Web Support
      Web支持,可以非常容易的集成到Web环境;
    6. Caching
      缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
    7. Concurrency
      shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    8. Testing
      提供测试支持;
    9. Run As
      允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    10. Remember Me
      记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    主要概念

    Subject

    当前的操作用户
    可以是人
    爬虫
    当前跟软件交互的东西
    在shiro当中我们可以统称"用户"
    在代码的任何地方,你都能轻易的获得Shiro Subject。
    一旦获得Subject,你就可以立即获得你希望用Shiro为当前用户做的90%的事情:登录、退、访问会话、执行授权检查等

    SecurityManager

    SecurityManager则管理所有用户的安全操作
    引用了多个内部嵌套安全组件,是Shiro框架的核心
    你可以把它看成DispatcherServlet前端控制器。
    用于调度各种Shiro框架的服务

    Realms

    Realms则是用户的信息认证器和用户的权限认证器
    执行认证(登录)和授权(访问控制)时,Shiro会从应用配置的Realm中查找很多内容
    Realm 可以理解为读取用户信息、角色及权限的 DAO
    SecurityManager要验证用户身份与权限,那么它需要从Realm获取相应的信息进行比较以确定用户身份是否合法;
    可以把Realm看成DataSource,即安全数据源。

    Shiro架构

    整体架构图
    在这里插入图片描述

    1. subject:主体
      主体可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
    2. securityManager:安全管理器
      主体进行认证和授权都是通过securityManager进行。
    3. authenticator: 认证器
      主体进行认证最终通过authenticator进行的。
    4. authorizer: 授权器
      主体进行授权最终通过authenticator进行的。
    5. sessionManager:会话管理
      web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。
    6. sessionDao:
      通过sessionDao管理session数据,
    7. cacheManager: 缓存管理器
      主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和 ehcache整合对缓存数据进行管理。
    8. realm: 领域
      相当于数据源,通过realm存取认证、授权相关数据。
    9. cryptography: 密码管理
      提供了一套加密/解密的组件,方便开发。比如 提供常用的散列、加/解密等功能。

    认证

    什么是认证

    身份认证,就是判断一个用户是否为合法用户的处理过程
    通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确

    关键对象

    1. Subject:主体
      用户
    2. Principal:身份信息
      是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等
    3. credential:凭证信息
      是只有主体自己知道的安全信息,如密码、证书等。

    使用ini完成认证

    1. 在Maven中添加依赖jar包
        <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-core</artifactId>  
            <version>1.4.0</version>  
        </dependency>  
    
    1. 添加shiro.ini配置文件
      首先准备一些用户身份/凭据(shiro.ini):
    [users]  
    itlike=1234
    my=1234
    
    1. 登录与退出

    1.构建securityManager工厂
    2.通过工厂创建securityManager
    3.将securityManager设置到运行环境中
    4.创建一个Subject实例
    5.创建token令牌
    6.用户登录
    7.用户退出
    在这里插入图片描述

    		/*1.构建securityManager工厂*/
            IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            /*2.通过工厂创建securityManager*/
            SecurityManager securityManager = factory.getInstance();
            /*3.将securityManager设置到运行环境中*/
            SecurityUtils.setSecurityManager(securityManager);
            /*4.创建一个Subject实例*/
            Subject subject = SecurityUtils.getSubject();
            /*5.创建token令牌  用户名和密码*/
            UsernamePasswordToken token = new UsernamePasswordToken("itlike", "1234");
            /*6.用户登陆*/
            try {
                subject.login(token);
            } catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
                e.printStackTrace();
            }catch (IncorrectCredentialsException e){
                System.out.println("密码错误");
                e.printStackTrace();
            }
            System.out.println("是否认证"+subject.isAuthenticated());
            /*7.用户退出*/
            subject.logout();
            System.out.println("是否认证"+subject.isAuthenticated());
    

    认证流程

    在这里插入图片描述
    认证代码执行流程

    1. 调用subject.login方法进行登录,其会自动委托给securityManager.login方法进行登录;
      在这里插入图片描述

    2. securityManager通过Authenticator(认证器)进行认证;
      在这里插入图片描述

    3.Authenticator的实现ModularRealmAuthenticator调用realm从ini配置文件取用户真实的账号和密码
    在这里插入图片描述

    1. IniRealm先根据token中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。
      在这里插入图片描述

    2. 最后调用Subject.logout进行退出操作。

    自定义realm

    1. 创建一个类继承AuthorizingRealm
    2. 覆盖doGetAuthenticationInfo方法,在此方法当中数据库获取用户,交有验证器去验证
      在这里插入图片描述
    3. 在ini文件当中进行配置
    myRealm=MyRealm
    securityManager.realms=$myRealm
    

    散列密码

    概述

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法 一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等

    使用shiro进行散列密码
    Md5Hash
    SimpleHash
    在这里插入图片描述

     Md5Hash md5Hash = new Md5Hash("itlike");
            System.out.println(md5Hash);
            /*通过加盐的方式来对密码进一步保护*/
            Md5Hash md5Hash2 = new Md5Hash("itlike","myxq");
            System.out.println(md5Hash2);
            /*可进行二次散列*/
            Md5Hash md5Hash3 = new Md5Hash("itlike","myxq",2);
            System.out.println(md5Hash3);
            /*使用SimpleHash*/
            SimpleHash simpleHash = new SimpleHash(
                    "md5",
                    "itlike",
                    "myxq",
                    2);
            System.out.println(simpleHash);
    

    realm中配置散列
    在ini文件当中进行散列
    在这里插入图片描述

    [main]
    #定义凭证匹配器
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #散列算法
    credentialsMatcher.hashAlgorithmName=md5
    #散列次数
    credentialsMatcher.hashIterations=3
    #指定realm
    myRealm=com.itlike.MyRealm
    #配置散列
    myRealm.credentialsMatcher=$credentialsMatcher
    #配置自定义散列
    securityManager.realms=$myRealm
    

    要保证数据库中的密码是经过散列之后的
    在这里插入图片描述
    在这里插入图片描述

    授权

    什么是授权

    授权,即访问控制,控制谁能访问哪些资源。
    主体进行身份认证后需要分配权限,方可访问系统的资源,对于某些资源没有权限是无法访问的。

    使用ini形式配置权限信息

    在ini文件中用户、角色、权限的配置规则
    用户名=密码,角色1,角色2...
    首先根据用户名找角色,再根据角色找权限,角色是权限集合。

    权限字符串的规则

    “资源标识符:操作:资源实例标识符”
    对哪个资源的哪个实例具有什么操作
    :”是资源/操作/实例的分割符
    权限字符串也可以使用*通配符
    示例在这里插入图片描述

    [users]
    #用户itlike的密码是1234,此用户具有role1和role2两个角色
    itlike=1234,role1,role2
    myxq=1234,role2
    [roles]
    #角色role1对资源user拥有create、update权限
    role1=user:create,user:update
    #角色role2对资源user拥有create、delete权限
    role2=user:create,user:delete
    #角色role3对资源user拥有create权限
    role3=user:create
    

    自定义Realm形式权限
    在这里插入图片描述

    /*获取身份信息*/
            Object principal = principals.getPrimaryPrincipal();
            /*根据用户名查询该用户的角色和权限*/
            List<String> roles = new ArrayList();
            roles.add("role1");
            roles.add("role2");
            List<String> permissions = new ArrayList();
            permissions.add("user:create");
            permissions.add("user:delete");
            /*把角色和权限与subject关联在一起,返回*/
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addRoles(roles);
            info.addStringPermissions(permissions);
    

    shiro.ini方式使用流程

    1. 创建maven工程
      在这里插入图片描述
      在这里插入图片描述
    2. 在Maven中添加依赖jar包. shiro核心jar&&依赖jar
      在这里插入图片描述
     <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>1.4.0</version>
        </dependency>
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-nop</artifactId>
          <version>1.7.30</version>
          <scope>test</scope>
        </dependency>
    
    1. 创建shiro.ini文件
      在这里插入图片描述
    2. 认证代码
      在这里插入图片描述
      在这里插入图片描述
    public static void main( String[] args ){
            /**
             * 1.构建securityManager工厂
             * 2.通过工厂创建securityManager
             * 3.将securityManager设置到运行环境中
             * 4.创建一个Subject实例
             * 5.创建token令牌
             * 6.用户登录
             * 7.用户退出
             */
    
            //1.构建securityManager工厂
            IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2.通过工厂创建securityManager
            SecurityManager securityManager = factory.getInstance();
            //3.将securityManager设置到运行环境中
            SecurityUtils.setSecurityManager(securityManager);
            //4.创建一个Subject实例
            Subject subject = SecurityUtils.getSubject();
            //5.创建token令牌
            UsernamePasswordToken token = new UsernamePasswordToken("joker", "1234");
            // 6.用户登录
            try {
                subject.login(token);
            }catch (UnknownAccountException e){
                /*账号不存在*/
                System.out.println("账号不存在");
    
            }catch (IncorrectCredentialsException e){
                /*密码错误*/
                System.out.println("密码错误");
            }
            System.out.println("是否认证成功"+subject.isAuthenticated());
            //7.用户退出
            subject.logout();
            System.out.println("是否认证成功"+subject.isAuthenticated());
        }
    

    自定义realm

    1. 创建一个类继承AuthorizingRealm
      在这里插入图片描述
    2. 自定义认证
      在这里插入图片描述
    /*认证AuthenticationInfo*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            /*判断用户名密码是否存在*/
            /*获取用户名*/
            String username=(String) token.getPrincipal();
            /*从数据库中查询密码*/
            String name="joker";
            String password="1234";
            if(!name.equals(username)){
                return null;
            }
    
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, this.getName());
            return info;
        }
    
    1. 在ini文件配置realm
      在这里插入图片描述
    myRealm=com.dj.myRealm
    securityManager.realms=$myRealm
    

    散列密码加盐
    配置散列信息
    在这里插入图片描述
    在这里插入图片描述
    4. 授权
    在 shiro-permission.ini配置文件配置
    在这里插入图片描述

    [users]
    #用户itlike的密码是1234,此用户具有role1和role2两个角色
    itlike=1234,role1,role2
    myxq=1234,role2
    
    [roles]
    #角色role1对资源user拥有create、update权限
    role1=user:create,user:update
    #角色role2对资源user拥有create、delete权限
    role2=user:create,user:delete
    #角色role3对资源user拥有create权限
    role3=user:create
    

    在这里插入图片描述

    		 System.out.println("是否认证成功"+subject.isAuthenticated());
            //在认证成功之后才去授权
            //判断当前用户是否有某个角色和
            System.out.println(subject.hasRole("role1"));
            /*判断当前用户是否有多个角色*/
            System.out.println(subject.hasAllRoles(Arrays.asList("role1", "role2")));
    
            /*判断使用有某个权限*/
            System.out.println(subject.isPermitted("user:update"));
            /*判断是否具备多个权限*/
            System.out.println(subject.isPermittedAll("user:create", "user:delete"));
    

    自定义Realm形式权限
    在这里插入图片描述

     /*授权AuthorizationInfo*/
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            /*获取身份信息*/
            Object principal = principals.getPrimaryPrincipal();
            /*根据用户名查询该用户的角色和权限*/  //从数据库查
            List<String> roles = new ArrayList();
            roles.add("role1");
            roles.add("role2");
            List<String> permissions = new ArrayList();
            permissions.add("user:create");
            permissions.add("user:delete");
            /*把角色和权限与subject关联在一起,返回*/
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addRoles(roles);
            info.addStringPermissions(permissions);
            return info;
        }
    

    SSM整合shiro

    在这里插入图片描述

    1. 添加依赖
    <dependencies>
        <!--Junit-->
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.46</version>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
          <groupId>com.mchange</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.5.2</version>
        </dependency>
    
        <!--Servlet - JSP -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.2</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>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.2</version>
        </dependency>
        <!-- druid -->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.0.14</version>
        </dependency>
        <!--Spring-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>5.1.9.RELEASE</version>
        </dependency>
    
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.16.10</version>
        </dependency>
        <dependency>
          <groupId>com.github.pagehelper</groupId>
          <artifactId>pagehelper</artifactId>
          <version>5.1.10</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.9.8</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.8</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
          <version>2.9.8</version>
        </dependency>
        <dependency>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-mapper-asl</artifactId>
          <version>1.9.13</version>
        </dependency>
        <!-- joda-time -->
        <dependency>
          <groupId>joda-time</groupId>
          <artifactId>joda-time</artifactId>
          <version>2.9.6</version>
        </dependency>
        <!--shiro-->
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-nop</artifactId>
          <version>1.7.24</version>
        </dependency>
        <dependency>
          <groupId>commons-collections</groupId>
          <artifactId>commons-collections</artifactId>
          <version>3.2.1</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>1.4.0</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-web</artifactId>
          <version>1.4.0</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-ehcache</artifactId>
          <version>1.4.0</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>1.4.0</version>
        </dependency>
      </dependencies>
    
    1. 在web.xml当中配置过滤器拦截所有请求,进行处理
     <!-- 拦截到所有请求,使用spring一个bean来进行处理 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <!-- 是否filter中的init和 destroy-->
            <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>
    

    web.xml

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             version="3.0"
             metadata-complete="false">
      <absolute-ordering/>
      <display-name>web</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    
      <!--配置前端控制器-->
      <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <!--加载的主配置文件-->
          <param-value>classpath*:applicationContext.xml</param-value>
        </init-param>
        <!-- 项目启动就加载框架 -->
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    
    
      <!-- 拦截到所有请求,使用spring一个bean来进行处理 -->
      <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <!-- 是否filter中的init和 destroy-->
        <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>
    </web-app>
    

    application-mvc.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    	">
    
        <mvc:annotation-driven />
        <!--静态资源处理 -->
        <mvc:default-servlet-handler/>
        <!--视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"/>
            <property name="suffix" value=".jsp" />
        </bean>
    
    
    </beans>
    

    application-mybatis.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:aop="http://www.springframework.org/schema/aop"
           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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
    ">
    
        <!--spring-Mybatis整合-->
        <!--加载数据库属性文件-->
        <context:property-placeholder location="classpath:db.properties"/>
        <!--连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driver}" />
            <!--属性文件当中的名称不能和name名称一样-->
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
        <!-- 配置事务管理器 -->
        <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 数据源 -->
            <property name="dataSource" ref="dataSource" />
        </bean>
        <!-- 开启注解事务 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <!-- Mybatis的工厂 -->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!-- 核心配置文件的位置 -->
            <property name="configLocation" value="classpath:sqlMapConfig.xml"/>
            <!--配置mapper映射文件的路径-->
            <property name="mapperLocations" value="classpath*:com/dj/mapper/*mapper.xml"/>
        </bean>
    
        <!-- 配置Mapper接口扫描 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- 配置Mapper扫描包 -->
            <property name="basePackage" value="com.dj.mapper" />
        </bean>
    
    </beans>
    

    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:aop="http://www.springframework.org/schema/aop"
           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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
    ">
        <!--注解扫描-->
        <context:component-scan base-package="com.dj"/>
        <!--导入mybatis-->
        <import resource="classpath:application-mybatis.xml"/>
    
        <!--导入springMVC-->
        <import resource="classpath:application-mvc.xml"/>
        <!--导入shiro-->
        <import resource="classpath:application-shiro.xml"/>
    
    </beans>
    

    db.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/permission?characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=123456
    

    sqlMapConfig.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!--<settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>-->
        <typeAliases>
            <!-- 批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感) -->
            <package name="com.dj.domain" />
        </typeAliases>
        <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor">
            </plugin>
        </plugins>
    </configuration>
    
    1. 在spring当中配置shiro过滤器和安全管理器 application-shiro.xml
      在这里插入图片描述
    2. 配置登录认证的路径
    <!-- 配置登录认证的路径 -->
    <property name="loginUrl" value="/login" />
    

    在这里插入图片描述
    5. 创建自定义realm
    在这里插入图片描述

     /*认证*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("来到了认证");
            String username=(String)token.getPrincipal();
            System.out.println(username);
            /*到数据中查询有没有当前用户*/
            employee employee = service.getEmployeeWithUsername(username);
            System.out.println(employee);
            if(employee==null){
                return null;
            }
            /*认证*/
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(employee,employee.getPassword(),this.getName());
            return info;
    
    1. 配置realm
      在这里插入图片描述
    2. 创建表单提交的过滤器 继承FormAuthenticationFilter
      在这里插入图片描述
    public class MyFormFilter extends FormAuthenticationFilter {
        /*认证成功会调用*/
        @Override
        protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
            response.setCharacterEncoding("UTF-8");
            /*响应给浏览器*/
            System.out.println("认证成功");
            AjaxRes ajaxRes = new AjaxRes(true, "登录成功");
            /*把对象转成json字符串*/
            String jsonString = new ObjectMapper().writeValueAsString(ajaxRes);
            response.getWriter().print(jsonString);
            return false;
        }
        /*认证失败 会调用*/
        @Override
        protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
            /*响应给浏览器*/
            System.out.println("认证失败");
            return false;
        }
    }
    
    1. 配置表单监听过滤器
      在这里插入图片描述
    2. 跳转首页
      在这里插入图片描述
    3. 认证失败
      在这里插入图片描述
      /*认证失败 会调用*/
        @Override
        protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
            /*响应给浏览器*/
             response.setCharacterEncoding("UTF-8");
            if(e!=null){
                /*获取异常名称*/
                String name = e.getClass().getName();
                AjaxRes ajaxRes=null;
                if(name.equals(UnknownAccountException.class.getName())){
                    /*账号不存在*/
                    ajaxRes = new AjaxRes(false, "账号不存在");
                }else if(name.equals(IncorrectCredentialsException.class.getName())){
                    /*密码错误*/
                     ajaxRes = new AjaxRes(false, "密码错误");
                }else {
                    /*未知异常*/
                     ajaxRes = new AjaxRes(false, "未知异常");
                }
                String jsonString = null;
                try {
                    jsonString = new ObjectMapper().writeValueAsString(ajaxRes);
                    response.getWriter().print(jsonString);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
    
            }
    
            return false;
        }
    

    在这里插入图片描述
    11. 设置注销url
    在这里插入图片描述
    12. 授权注解
    在这里插入图片描述
    配置支持shiro注解

    在这里插入图片描述

    <!--
        配置为true即使用cglib继承的方式,
        false为jdk的接口动态代理   控制器没有实现接口
        -->
        <aop:config proxy-target-class="true" ></aop:config>
        <!-- 使用第三方去扫描shiro的注解 -->
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor ">
            <property name="securityManager" ref="securityManager"></property>
        </bean>
    
    1. 授权realm
      在这里插入图片描述
        /*授权*/
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            System.out.println("来到了授权");
            employee employee = (employee)principal.getPrimaryPrincipal();
            List<String> roles=service.getroleById(employee.getId());
            List<String> permission=service.getpermission(employee.getId());
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addRoles(roles);
            info.addStringPermissions(permission);
            return info;
        }
    
    1. 授权标签
    <shiro:hasPermission name=""></shiro:hasPermission>
    <shiro:hasRole name=""></shiro:hasRole>
    
    1. 散列加密
      在这里插入图片描述
      在这里插入图片描述
    <!-- 凭证匹配器 -->
    	<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    		<!-- 散列算法 -->
    		<property name="hashAlgorithmName" value="md5"/>
    		<!-- 散列次数 -->
    		<property name="hashIterations" value="2"></property>
    	</bean>
    
    
    	<!--自定义realm-->
    	<bean id="employeeRealm" class="com.dj.web.realm.EmplyeeRealm">
    		<property name="credentialsMatcher" ref="credentialsMatcher"/>
    	</bean>
    
    1. 权限缓存 shiro-ehcache.xml
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
        <defaultCache
                maxElementsInMemory="1000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        </defaultCache>
    </ehcache>
    

    在这里插入图片描述
    shiro.xml
    在这里插入图片描述
    17. 菜单权限

    /*获取树形菜单数据*/
        @RequestMapping("/getTreeData")
        @ResponseBody
        public List<menu> getTreeData(){
            List<menu> treeData = service.getTreeData();
            System.out.println(treeData);
            /*判断权限
            如果没有就移除
            * */
            /*获取用户*/
            Subject subject = SecurityUtils.getSubject();
            /*当前用户*/
            employee employee =(employee) subject.getPrincipal();
            if(!employee.getAdmin()){
                /*不是管理员 校验权限*/
                chePermission(treeData);
            }
            return treeData;
        }
        /*校验权限*/
        public void chePermission(List<menu> menus){
            Subject subject = SecurityUtils.getSubject();
            /*遍历所有菜单 及子菜单*/
            Iterator<menu> iterator = menus.iterator();
            while (iterator.hasNext()) {
                menu m = iterator.next();
                if(m.getPermission()!=null){
                    /*判断当前菜单是否有权限  没有就移除*/
                    String presources = m.getPermission().getPresources();
                    if(!subject.isPermitted(presources)){
                        /*没有 从菜单集合 移除*/
                        iterator.remove();
                        continue;
                    }
                }
                /*判断是否有子菜单 如果有 继续做校验*/
                if(m.getChildren().size()>0){
                    chePermission(m.getChildren());
                }
    
            }
        }
    
  • 相关阅读:
    React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton)
    React Native之TextInput的介绍与使用(富文本封装与使用实例,常用输入框封装与使用实例)
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
  • 原文地址:https://www.cnblogs.com/joker-dj/p/13388734.html
Copyright © 2011-2022 走看看