shiro安全框架从入门到精通实战!!!!

    2025-05-03 15:41:01

    shiro面试题1、String是不是基本的数据类型?

    代码语言:javascript代码运行次数:0运行复制不是,是引用类型。 地址在 栈 中存放, 值:堆;

    基本类型:整形,浮点型、布尔型、字符型。;栈2、abstaract的mehtod能不能是static,同时是native, 同步的?

    代码语言:javascript代码运行次数:0运行复制抽象类中可以有静态方法的。

    抽象方法不能是静态的,需要被子类实现。静态方法无法被子类实现。

    native:本地的。

    不能???3、String和StringBuffer、StringBuilder的区别?

    代码语言:javascript代码运行次数:0运行复制String是不可变的的实例对象。

    StringBuffer:线程安全

    StringBuilder:线程不安全的4、实现多态的机制?

    代码语言:javascript代码运行次数:0运行复制1、继承关系(子类继承父类,子类实现接口)

    2、父类引用 指向 子类对象;

    3、子类要实现或者重写父类的方法

    List list=new ArrayList();

    List list=new LinkedList(); 5、数组中有没有length方法,string中有没有length方法;

    代码语言:javascript代码运行次数:0运行复制数组:length属性;

    String中:length()方法;学习目标1、shiro介绍

    2、Springboot整合Shiro

    学习内容1.shiro介绍1.1介绍shiro是一个java的 安全框架,apache的一个开源框架。简单易用。实现的功能:认证、授权、会话管理和密码加密等功能。可以用在java SE环境中,java EE环境中。1.2shrio功能特点:Authentication:认证

    Authorization:授权

    Session Management:session会话管理

    Cryptography:密码加密

    Caching:缓存

    web Support:web支持

    Concurrency:多线程、并发

    Testing:测试

    Run as: 以 某种 身份 运行

    Remember Me:记住我

    什么是认证:Authentication

    通过用户名和密码,或者人脸识别,或者是指纹跟数据库里的数据进行匹配,如果匹配成功则代表认证通过;

    什么是授权:Authorization

    认证通过后,对不同的资源的访问进行控制,这就是授权的体现;

    身份:用户名

    凭证:密码

    1.3shiro运行原理Subject:主体,抽象的身份:当前的用户,网络爬虫、第三方的程序、进程

    SecurityManager:安全管理器,管理所有的subjects;委托给SecurityManager进行安全管理。门面模式:Facade;需求----》委托人————分发下去;

    Realm:域,数据域。获取数据库中用户信息、权限信息。

    前台用户输入用户名和密码,点击登陆后,会使用一个subject进行login;

    subject使用securitymanager.login方法进行登陆;

    realm:数据域,它会处理login,会拿着前台输入的用户名和密码进行与数据库里的用户名和密码进行匹配,如果匹配成功,则认证通过;

    代码语言:javascript代码运行次数:0运行复制//常用过滤器

    /*

    * anon:不需要认证就可以访问呢

    *authc:必须认证才可以访问

    * user:如果实现remenberme可以直接访问

    * perms:必须授权才可以访问

    * role:必须得到角色才可以访问

    * */2、shiro的认证步骤2.1创建springboot项目导入mybatis整合依赖;

    导入MySQL驱动依赖;

    导入druid依赖;

    导入thymeleaf 依赖;

    导入shiro和spring的整合依赖;

    导入shiro和thymeleaf的整合依赖;

    代码语言:javascript代码运行次数:0运行复制

    org.mybatis.spring.boot

    mybatis-spring-boot-starter

    1.3.2

    com.alibaba

    druid

    1.1.19

    mysql

    mysql-connector-java

    8.0.16

    com.github.pagehelper

    pagehelper-spring-boot-starter

    1.2.3

    com.github.theborakompanioni

    thymeleaf-extras-shiro

    2.0.0

    org.apache.shiro

    shiro-spring

    1.2.3

    2.2配置文件properties文件书写:

    代码语言:javascript代码运行次数:0运行复制server.servlet.context-path=/demo

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true

    spring.datasource.username=root

    spring.datasource.password=123@qwe

    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

    spring.resources.static-locations=classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/templates/

    mybatis.type-aliases-package=com.aaa.demo_shiro.entity

    pagehelper.helperDialect = mysql

    pagehelper.reasonable = true

    pagehelper.supportMethodsArguments = true

    pagehelper.pageSizeZero = true

    pagehelper.params = countSql

    logging.level.com.aaa.demo_shiro.mapper=debug

    spring.thymeleaf.cache=false

    spring.main.banner-mode=off2.3从之前的项目中把班级管理拿过来再把权限的五张表的数据拿过来;

    在pom.xml文件中添加resources;

    代码语言:javascript代码运行次数:0运行复制

    src/main/java

    **/*.xml

    false

    src/main/resources

    **/*.*

    false

    2.4创建ShiroConfiguration类该类是shiro的配置文件:

    在该类中需要建立四个bean:

    代码语言:javascript代码运行次数:0运行复制package com.example.demo_shiro.config;

    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;

    @Configuration

    public class ShiroConfig {

    //realm 是自己定义的,用来实现前台的用户信息和数据库的用户信息进行匹配

    @Bean(name="userRealm")

    public UserRealm getUserRealm(){

    UserRealm userRealm = new UserRealm();

    return userRealm;

    }

    //安全管理器securitymanager

    @Bean(name="securityManager")

    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){

    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

    securityManager.setRealm(userRealm);

    return securityManager;

    }

    //过滤器连工厂shirofilterfactorybean

    @Bean(name="shiroFilterFactoryBean")

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    return shiroFilterFactoryBean;

    }

    //密码匹配器

    //shiro 与thymeleaf的整合

    }2.5创建测试页面、登陆、添加、修改页面然后创建对应的controller方法

    2.6修改和添加页面只有认证后才可以访问在ShiroConfiguration中添加认证过滤

    代码语言:javascript代码运行次数:0运行复制 @Bean(name="shiroFilterFactoryBean")

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    shiroFilterFactoryBean.setSecurityManager(securityManager);

    Map filtermap = new LinkedHashMap();

    filtermap.put("/test","anon");

    filtermap.put("/login","anon");

    filtermap.put("/**","authc");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);

    shiroFilterFactoryBean.setLoginUrl("toLogin");

    return shiroFilterFactoryBean;

    }2.7修改认证逻辑在controller方法的登陆方法中

    代码语言:javascript代码运行次数:0运行复制三个步骤:

    1.获取subject

    2.封装token

    3.登陆

    @RequestMapping("login")

    public String login(String username,String password,Model model){

    System.out.println(username+"-->"+password);

    //第一步获取subject

    Subject subject = SecurityUtils.getSubject();

    //封装token

    UsernamePasswordToken token = new UsernamePasswordToken(username,password);

    //第三步login方法

    try {

    subject.login(token);

    return "login";

    } catch (UnknownAccountException e) {

    model.addAttribute("msg","不存在该用户!");

    return "login";

    } catch (IncorrectCredentialsException e) {

    model.addAttribute("msg","密码凭证错误!");

    return "login";

    }catch (Exception e){

    model.addAttribute("msg","未知错误!");

    return "login";

    }

    }2.8实现密码认证自己定义一个密码加密器

    代码语言:javascript代码运行次数:0运行复制public class UserCredentialsMatcher {

    /**

    * 随机生成 salt 需要指定 它的字符串的长度

    *

    * @param len 字符串的长度

    * @return salt

    */

    public static String generateSalt(int len) {

    //一个Byte占两个字节

    int byteLen = len >> 1;

    SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();

    return secureRandom.nextBytes(byteLen).toHex();

    }

    /**

    * 获取加密后的密码,使用默认hash迭代的次数 1 次

    *

    * @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。

    * @param password 需要加密的密码

    * @param salt 盐

    * @return 加密后的密码

    */

    public static String encryptPassword(String hashAlgorithm, String password, String salt) {

    return encryptPassword("MD5", password, salt, 2);

    }

    /**

    * 获取加密后的密码,需要指定 hash迭代的次数

    *

    * @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。

    * @param password 需要加密的密码

    * @param salt 盐

    * @param hashIterations hash迭代的次数

    * @return 加密后的密码

    */

    public static String encryptPassword(String hashAlgorithm, String password, String salt, int hashIterations) {

    SimpleHash hash = new SimpleHash(hashAlgorithm, password, salt, hashIterations);

    return hash.toString();

    }

    }在ShiroConfig中定义凭证匹配器

    代码语言:javascript代码运行次数:0运行复制//密码匹配器

    @Bean(name="hashedCredentialsMatcher")

    public HashedCredentialsMatcher getHashedCredentialsMatcher(){

    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

    hashedCredentialsMatcher.setHashAlgorithmName("MD5");

    hashedCredentialsMatcher.setHashIterations(2);

    return hashedCredentialsMatcher;

    }给realm设置匹配器

    代码语言:javascript代码运行次数:0运行复制@Bean(name="userRealm")

    public UserRealm getUserRealm(@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher hashedCredentialsMatcher){

    UserRealm userRealm = new UserRealm();

    userRealm.setCredentialsMatcher(hashedCredentialsMatcher);

    return userRealm;

    }在realm中设置如下:

    代码语言:javascript代码运行次数:0运行复制SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),getName());3.shiro的授权步骤3.1 测试授权代码语言:javascript代码运行次数:0运行复制@Bean(name="shiroFilterFactoryBean")

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    shiroFilterFactoryBean.setSecurityManager(securityManager);

    Map filtermap = new LinkedHashMap();

    filtermap.put("/test","anon");

    filtermap.put("/login","anon");

    filtermap.put("/user/add","perms[user:add]");

    filtermap.put("/user/update","perms[user:update]");

    filtermap.put("/classes/findall","perms[classes:findall]");

    filtermap.put("/**","authc");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);

    shiroFilterFactoryBean.setLoginUrl("/toLogin");

    shiroFilterFactoryBean.setSuccessUrl("/hello");

    shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");

    return shiroFilterFactoryBean;

    }3.2授权代码语言:javascript代码运行次数:0运行复制 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

    System.out.println("执行授权方法");

    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

    //获取当前认证过的用户

    Subject subject = SecurityUtils.getSubject();

    SysUser user = (SysUser) subject.getPrincipal();

    //查询该用户所有的授权

    List ps = null;

    try {

    ps = sysService.findPermissionListByUserId(user.getId());

    } catch (Exception e) {

    e.printStackTrace();

    }

    Set permissions = new HashSet();

    for(SysPermission p:ps){

    permissions.add(p.getPercode());

    }

    info.setStringPermissions(permissions);

    return info;

    }3.3不同的授权看到不同的资源添加依赖

    代码语言:javascript代码运行次数:0运行复制

    com.github.theborakompanioni

    thymeleaf-extras-shiro

    2.0.0

    在配置类中添加bean

    代码语言:javascript代码运行次数:0运行复制//配置shiroDialect,用于thymeleaf和shiro的合用

    @Bean

    public ShiroDialect getShiroDialect(){

    return new ShiroDialect();

    }在test前端写代码

    代码语言:javascript代码运行次数:0运行复制

    xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

    测试界面

    班级管理:班级管理

    用户添加:添加用户

    用户修改:修改用户