Shiro 基础

本贴最后更新于 1554 天前,其中的信息可能已经渤澥桑田

老物


新的公司让我去熟悉下Shiro框架,公司的项目的权限管理都是基于Shiro写的,照着前辈们的blog学习了一番,这里做点个人学习记录。*

Shiro 的整体架构图

Shiro 架构图


首先是 Shiro 的几个组件

  • SecurityManager
    即所有 Subject 的管理者,这是 Shiro 框架的核心组件,可以把他看做是一个 Shiro 框架的全局管理组件,用于调度各种 Shiro 框架的服务。
  • Authenticator
    认证器,登入登出,对“Who are you?”进行核实。通常涉及用户名和密码。
  • Authorizer
    授权器,赋予主体有哪些权限,身份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、用户组、角色和 permission 的聚合体。
  • Session Manager
    这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户端或者协议绑定。
  • Subject
    即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro 中则需要通过 Subject 来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。
  • Realms
    Realms 也就是域,是用户的信息认证器和用户的权限人证器,我们需要自己来实现 Realms 来自定义的管理我们自己系统内部的权限规则。

通过 ini 文件来自定义 Realm

Maven 依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.2.3</version>
</dependency>

shiro.ini

# -----------------------------------------------------------------------------
# Users and their (optional) assigned roles
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]

#用户名(登陆账号)是root,密码是123,角色是admin管理员

root = 123,admin
user001 = 123,productManager
user002 = 123,orderManager

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]

#admin管理员权限拉满,什么都能做
admin = *

#产品经理只能做产品的管理
productManager = addProduct,deleteProduct,editProduct,listProduct

#订单管理员只能做订单的管理
orderManager = addOrder,deleteOrder,editOrder,listOrder

这里分配了三种角色各自拥有不同的权限

  • admin

    • 拥有所有权限
  • productManager

    • addProduct
    • deleteProduct
    • editProduct
    • listProduct
  • orderManager

    • addOrder
    • deleteOrder
    • editOrder
    • listOrder

Tutorial .java

package shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by MatthewHan on 2018.
 */
public class Tutorial {

    private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
    public static void main(String[] args) {

        //step1.使用了IniSecurityManagerFactory类读取ini文件
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        
        //step2.解析ini文件,返回一个Securitymanager对象,对象含有配置信息
        SecurityManager securityManager = factory.getInstance();
        
        //step3.
        SecurityUtils.setSecurityManager(securityManager);


        //获取当前使用的用户
        Subject currentUser  = SecurityUtils.getSubject();
        //获取Session信息
        Session session = currentUser.getSession();
        session.setAttribute("oneKey","aValue");
        String value = (String)session.getAttribute("oneKey");
        if(value.equals("trueValue"))
        {
            log.info("值正确!["+ value +"]");
        }
        else
        {
            log.info("value有错误哦!您的value:["+ value+"]");
        }
    
        log.info("\n**********************是否登陆成功*********************\n");
    
        //登陆后的当前用户,这样我们就可以检查角色和权限:
        if(!currentUser.isAuthenticated()) {
            String username = "user001", password = "1123";
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            token.setRememberMe(true);
    
            try {
                currentUser.login(token);//登陆
                log.info("你居然登陆上了,牛逼");
                log.info("\n**********************打印这些登陆用户的信息*********************\n");
    
                //打印这些登陆用户的信息
                log.info("用户[" + currentUser.getPrincipal() + "] 登陆成功!");
    
                //测试一个role
                String roleName = "productManager";
                if (currentUser.hasRole(roleName)) {
                    log.info("这个角色:[" + roleName + "]");
                } else {
    
                    log.info("emmmm,mere mortal!");
                }
                log.info("\n**********************测试不同类型的权限*********************\n");
    
                //测试不同类型的权限
                if (currentUser.isPermitted("addProduct")) {
                    log.info("您可以对产品进行管理");
                } else {
                    log.info("你不配使用");
                }
    
                //part2
                if (currentUser.isPermitted("addOrder")) {
                    log.info("您可以对订单系统进行管理");
                }
                else{
                    log.info("抱歉,你不配管理订单系统");
                }


            } catch (UnknownAccountException uae) {
                log.info("没有这个用户名:" + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("这个账号" + token.getPrincipal() + "的密码是错的啦,try again?");
            } catch (LockedAccountException lae) {
                log.info("这个用户" + token.getPrincipal() + "已被封锁" + "请联系管理员解锁");
            } catch (AuthenticationException ae) {
                log.info("发生了一些未知的情况,请联系管理员!");
            }
    
        }


        //用户登出
        currentUser.logout();
        System.exit(0);
    
    }
}

测试类 Tutorial,通过 UsernamePasswordToken 创建的 token 对象来让 Subject (当前对象)进行登陆验证,认证通过后,可以用 getPrincipal() 这个方法来获取当前对象的用户名。

角色相关验证方法

Subject 方法 描述
hasRole(String roleName) 当用户拥有指定角色时,返回 true
hasRoles(List roleNames) 按照列表顺序返回相应的一个 boolean 值数组
hasAllRoles(Collection roleNames) 如果用户拥有所有指定角色时,返回 true

Subject 方法 描述
checkRole(String roleName) 断言用户是否拥有指定角色
checkRoles(Collection roleNames) 断言用户是否拥有所有指定角色
checkRoles(String... roleNames) 对上一方法的方法重载

权限相关验证方法

Subject 方法 说明
checkPermission(Permission p) 断言用户是否拥有制定权限
checkPermission(String perm) 断言用户是否拥有制定权限
checkPermissions(Collection perms) 断言用户是否拥有所有指定权限
checkPermissions(String... perms) 断言用户是否拥有所有指定权限

Subject 方法 描述
isPermitted(Permission p) Subject 拥有制定权限时,返回 true
isPermitted(List perms) 返回对应权限的 boolean 数组
isPermittedAll(Collection perms) Subject 拥有所有制定权限时,返回 true

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...