• Springboot集成shiro框架:


    1, Shiro:是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

    使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

    2,三大组件:Subject、SecurityManager、Realm

    Subject:
    即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。

    Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。

    SecurityManager:
    它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

    Realm:
    Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

    从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。

    Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
     

    3,基本功能点:

    Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
    Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
    Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    Web Support:Web 支持,可以非常容易的集成到 Web 环境;
    Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
    Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    Testing:提供测试支持;
    Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    4,springboot集成shiro框架和mybatis框架,以及Thymeleaf模板:

            1,创建一个springboot项目。

            2,导入相关依赖:


           
                org.apache.shiro
                shiro-spring
                1.8.0
           

    
    
        com.github.theborakompanioni
        thymeleaf-extras-shiro
        2.0.0
    
    
        mysql
        mysql-connector-java
    
    
        log4j
        log4j
        1.2.17
    
    
    
        com.alibaba
        druid
        1.1.12
    
    
    
        org.mybatis.spring.boot
        mybatis-spring-boot-starter
        2.1.0
    
    
    
        org.projectlombok
        lombok
    
    
        org.springframework.boot
        spring-boot-starter-thymeleaf
        2.6.1
    

            3,创建各个类

    bean

    package com.bean;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
    
        private int id;
        private String name;
        private String password;
        private String perms;
    }

    service

    接口:

    package com.secvice;
    
    import com.bean.Student;
    
    public interface IStudentService {
    
        public Student queryStudentByName(String name);
    }

    实现类:

    package com.secvice;
    
    import com.bean.Student;
    import com.mapper.StudentMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class StudentServiceImpl implements IStudentService {
    
        @Autowired
        StudentMapper studentMapper;
    
        @Override
        public Student queryStudentByName(String name) {
            return studentMapper.queryStudentByName(name);
        }
    }

    controller

    package com.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class MyController {
    
        @RequestMapping({"/index","/"})
        public String index(Model model){
            model.addAttribute("msg","hello shiro!!!");
            return "index";
        }
        @RequestMapping("/user/add")
        public String add(){
            return "user/add";
        }
        @RequestMapping("/user/update")
        public String update(){
            return "user/update";
        }
        @RequestMapping("/toLogin")
        public String toLogin(){
            return "login";
        }
    
        @RequestMapping("/login")
        public String login(String username,String password,Model model){
            //获取当前的用户
            Subject subject = SecurityUtils.getSubject();
            //用于封装用户的登录数据
            UsernamePasswordToken usernamePasswordToken
                    = new UsernamePasswordToken(username,password);
            try{
                subject.login(usernamePasswordToken);//执行登录方法,如果没有异常说明OK
                return "index";
            }catch (UnknownAccountException u){//用户名不存在
                model.addAttribute("msges","用户名错误!!!");
                return "login";
            }catch (IncorrectCredentialsException i){
                model.addAttribute("msges","密码错误!!!");
                return "login";
            }
        }
        @RequestMapping("/unauthorized")
        @ResponseBody
        public String unauthorized(){
            return "未经授权不可登录!!!";
        }
    }

    mapper

    mapper接口类:
    
    package com.mapper;
    
    import com.bean.Student;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Repository;
    
    @Repository
    @Mapper
    public interface StudentMapper {
    
        public Student queryStudentByName(String name);
    
    }
    mapper.xml:
    
    
    
    
    
        
    
    

    HTML页面:

            index.html

    
    
    
        
        首页
    
    
    
    

    首页

            login.html

    
    
     
         
        登录 
    
    
    
    




            add.html和update.html

     add.html:
    
    
    
    
        
        增加
    
    
    

    增加

    update.html:
    
    
    
    
        
        修改
    
    
    

    修改

    application.properties

    mybatis.type-aliases-package=com.bean
    mybatis.mapper-locations=classpath:mapper/*.xml

    application.yml

    spring:
      datasource:
        username: root
        password: root
        #?serverTimezone=UTC解决时区的报错
        url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
    
        #Spring Boot 默认是不注入这些属性值的,需要自己绑定
        #druid 数据源专有配置
        initialSize: 5
        minIdle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
    
    
        #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
        #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
        #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
        filters: stat,wall,log4j
        maxPoolPreparedStatementPerConnectionSize: 20
        useGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

    ShiroConfig配置类:

    package com.config;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    @Configuration
    public class ShiroConfig {
    
        //ShiroFilterFactoryBean
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
    
            //添加shiro的内置过滤器
            /*anon:无需认证就可以访问
           * authc:必须认证了才能访问
           * user:必须有记住我功能才能使用
           * perms:拥有对某个资源的权限才能访问
           * role:拥有某个角色权限才能访问
            *
            * */
    
            Map filterChainDefinitionMap=new LinkedHashMap<>();
    //        filterChainDefinitionMap.put("/user/add","authc");
    //        filterChainDefinitionMap.put("/user/update","authc");
            //授权,正常情况下,没有授权会跳到授权页面
            filterChainDefinitionMap.put("/user/add","perms[user:add]");
            filterChainDefinitionMap.put("/user/update","perms[user:update]");
    
            filterChainDefinitionMap.put("/user/*","authc");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    
            //跳转到登录页面
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
    
            //跳转到未授权页面
            shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
            return shiroFilterFactoryBean;
        }
    
        //DafaultWebSecurityManager
        @Bean//@Qualifier("userRealm")和userRealm关联
        public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
            //关联userRealm
            defaultWebSecurityManager.setRealm(userRealm);
            return defaultWebSecurityManager;
        }
    
        //创建realm 对象 ,需要自定义类
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    
        //整合shiro和thymeleaf模版
        @Bean
        public ShiroDialect shiroDialect(){
            return new ShiroDialect();
        }
    
    }
    
    UserRealm类:
    package com.config;
    
    import com.bean.Student;
    import com.secvice.IStudentService;
    import org.apache.catalina.security.SecurityUtil;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        IStudentService studentService;
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了==>授权doGetAuthorizationInfo");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                //授权add页面
                info.addStringPermission("user:add");
                //拿到当前登录的对象
               Subject subject = SecurityUtils.getSubject();
               //拿到student对象
            Student currentStudent = (Student) subject.getPrincipal();
            //添加权限访问
            info.addStringPermission(currentStudent.getPerms());
    
    
            return info;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行了==>认证doGetAuthenticationInfo");
    
            //获取登录用户的令牌,名字
            UsernamePasswordToken authenticationToken1 = (UsernamePasswordToken) authenticationToken;
            //连接数据库真实数据:用户名 密码
            Student student = studentService.queryStudentByName(authenticationToken1.getUsername());
            //判断数据库查询出来的不为空,为空则返回报错
            if(student==null){
                return null;
            }
            Subject currentSubject = SecurityUtils.getSubject();
            Session session = currentSubject.getSession();
            session.setAttribute("loginStudent",student);
    
            //密码认证,shiro自己判断
            return new SimpleAuthenticationInfo(student,student.getPassword(),"");
        }
    }
    
    
    
    
    

    数据库表,如图:

     

    创建包文件大概如下:

     以上大概是shiro的学习总结!!!

  • 相关阅读:
    负载均衡策略
    机智云工业级4G Cat.1 DTU全面升级数据采集485/232 GC521
    Slim GAIN(SGAIN)介绍及代码实现——基于生成对抗网络的缺失数据填补
    MES管理系统的应用和好处有哪些
    【JDBC Part 1】概述、获取连接、CRUD
    如何理解Linux字符设备驱动?
    行业标杆 | 海云安荣获中国信息通信研究院个人信息处理“最小必要”优秀案例
    LeetCode-1402题解
    Softing物联网(IoT)方案之OT/IT数据集成
    vscode 代码片段,快捷注释
  • 原文地址:https://blog.csdn.net/Li_582258/article/details/128152782