Shiro之温故而知新

本文深入探讨Apache Shiro框架的权限管理机制,包括认证与授权的抽象对象模型,如Subject、Principal、Credential、Resource和Permission。同时,文章详细介绍了Shiro在SpringBoot中的整合过程,包括配置过滤器、创建自定义Realm及实现认证与授权的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Shiro分为认证和授权
在这里插入图片描述

认证中抽象出来的对象

Subject:主体

访问系统的用户,主体可以是用户,程序等。进行认证的都成为主体。

Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以
有多个身份,但是必须有一个主身份(Primary Principal),比如手机号登录,或者账户登录。

Credential:凭证信息

是只有主体自己知道的安全信息,如密码、证书等。

授权中抽象出来的对象

授权可简单理解为who对what(which)进行How操作:

Who,即主体(Subject)

主体需要访问系统中的资源。

What,即资源(Resource)

如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。

How,权限/许可(Permission)

规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作
许可。

权限分为粗颗粒和细颗粒,粗颗粒权限是指对资源类型的权限,细颗粒权限是对资源实例的权限

shiro架构图

在这里插入图片描述

权限模型

在这里插入图片描述

shiro的授权

subject.isAuthenticated()							//登录是否成功
subject.hasRole("admin")							//验证是否有admin角色
subject.hasAllRoles(Arrays.asList("admin","super"))		//验证是否包含所有角色
subject.hasRoles(Arrays.asList("admin","super"))		//验证是否有某一个角色
subject.isAuthenticated()							//验证是否登录成功
subject.isPermitted("user:delete")					//验证用户是否有该权限

web页面shiro标签

<shiro:authenticated></shiro:authenticated>			//已经认证
<shiro:notAuthenticated></shiro:notAuthenticated>	//未认证
<shiro:principal></shiro:principal>					//获取主身份信息

<shiro:hasRole name="admin"></shiro:hasRole>						//判断是否有该角色
<shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles>		//判断是否有某一个角色(有一个就可执行)

<shiro:hasPermission name="banner:delete"></shiro:hasPermission>		//判断是否有该权限

认证和授权流程图

在这里插入图片描述

SpringBoot整合Shiro

引入依赖

 <dependency>
     <groupId>org.apache.shiro</groupId>
     <artifactId>shiro-spring-boot-web-starter</artifactId>
     <version>1.4.1</version>
 </dependency>

在这里插入图片描述
创建shiro过滤器

package cn.czboy.shiro;

import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Configuration
public class ShiroFilter {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        System.out.println("===========shiroFilter");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        HashMap<String,String> map = new HashMap<>();
        map.put("/subject/**","anon");
        map.put("/login.jsp","anon");
        map.put("/index.jsp","anon");
        map.put("/**","authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        shiroFilterFactoryBean.setLoginUrl("/login.jsp");//设置拦截后跳转的网页
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm myRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        MemoryConstrainedCacheManager cache = new MemoryConstrainedCacheManager();
        securityManager.setCacheManager(cache);
        securityManager.setRealm(myRealm);
        return securityManager;
    }

    @Bean
    public MyRealm myRealm() {
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }
}

创建自定义Realm

package cn.czboy.shiro;

import cn.czboy.entity.Role;
import cn.czboy.entity.Subject;
import cn.czboy.mapper.SubjectDao;
import cn.czboy.utils.SpringContextUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class MyRealm extends AuthorizingRealm {


    /**授权*/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String)principalCollection.getPrimaryPrincipal();
        SubjectDao subjectDao = (SubjectDao)SpringContextUtil.getBean(SubjectDao.class);
        //根据主体获取角色
        List<Role> roles = subjectDao.findByRole(username);
		
       	HashSet<String> set = new HashSet<>();
        ArrayList<String> arrayList = new ArrayList<>();
       
        SimpleAuthorizationInfo authorizationInfo = null;
        if(primaryPrincipal.equals(admin.getUsername())){
            authorizationInfo = new SimpleAuthorizationInfo();

            for(RoleDto role:roles){
                arrayList.add(role.getRoleName());
                String id = role.getId();
                //根据角色查权限
                List<String> permissionss = adminService.findByPermission(id);
                for(String key:permissionss){
                    set.add(key);
                }
            }

            authorizationInfo.addStringPermissions(set);//权限赋值
            authorizationInfo.addRoles(arrayList);//角色赋值
        }

        return authorizationInfo;
    }

    /**认证*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String)authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());
        SubjectDao subjectDao = (SubjectDao)SpringContextUtil.getBean(SubjectDao.class);
        Subject subject = subjectDao.findByUserName(username);
        AuthenticationInfo authenticationInfo = null;
        if (subject == null) {
            throw new UnknownAccountException("账户不存在!");
        }
        if (!subject.getUsername().equals(username)) {
            throw new UnknownAccountException("用户名错误!");
        }
        if (!subject.getPassword().equals(password)) {
            throw new IncorrectCredentialsException("密码错误!");
        }
        authenticationInfo  = new SimpleAuthenticationInfo(subject.getUsername(), subject.getPassword(), this.getName());
        System.out.println("================="+subject);
        return authenticationInfo;
    }
}

SubjectController

package cn.czboy.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.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/subject")
public class SubjectController {

    /**用户登陆*/
    @RequestMapping("/login")
    public String login(String username,String password) {
        System.out.println("========="+username);
        System.out.println("========="+password);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            return "yes";
        } catch (UnknownAccountException e) {
            System.out.println(e.getMessage());
            return "no";
        } catch (IncorrectCredentialsException e) {
            System.out.println(e.getMessage());
            return "no";
        }
    }
}

以下是重新表述后的内容: 单周期 MIPS CPU 的微程序地址转移逻辑设计:在单周期 MIPS CPU 架构中,微程序地址转移逻辑是关键部分。它负责根据当前微指令的执行情况以及 CPU 内部的各种状态信号,准确地计算出下一条微指令的地址。这一逻辑需要综合考虑指令类型、操作完成情况、是否发生异常等多种因素,以确保微程序能够按照正确的顺序和逻辑进行执行,从而实现 MIPS 指令的准确译码与控制。 MIPS 微程序 CPU 的设计:设计一款基于微程序控制的 MIPS CPU,其核心在于构建微程序控制器。该控制器通过存储微指令序列来实现对 CPU 各部件的控制。微指令中包含对数据通路操作的控制信号以及微程序地址转移信息。在设计过程中,需要精心设计微指令格式,使其能够高效地表示各种操作控制信息,同时合理安排微指令存储器的组织结构,确保微指令的快速读取与准确执行,从而实现 MIPS 指令集的完整功能。 MIPS 硬布线控制器的状态机设计:在采用硬布线控制方式的 MIPS CPU 中,状态机是控制器的核心组成部分。状态机根据输入的指令操作码、状态信号等信息,在不同的状态之间进行转换。每个状态对应着 CPU 在执行一条指令过程中的一个特定阶段,如取指、译码、执行、访存等。状态机的设计需要精确地定义各个状态的转换条件以及在每个状态下输出的控制信号,以确保 CPU 能够按照正确的时序和逻辑完成指令的执行过程。 多周期 MIPS 硬布线控制器 CPU 设计(排序程序):设计一款多周期 MIPS 硬布线控制器 CPU,用于运行排序程序。在这种设计中,CPU 的每个指令执行周期被划分为多个子周期,每个子周期完成指令执行过程中的一个特定操作。硬布线控制器根据指令操作码和当前周期状态,生成相应的控制信号来协调 CPU 数据通路的操作。针对排序程序的特点,需要优化控制器的设计,合理安排指令执行的周期划分
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值