Shiro入门学习一

Shiro简介

Apache Shiro 是一个强大易用的 Java 安全(权限)框架,提供了认证、授权、加密、会话管理、与Web集成和缓存等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务,相较于 Spring Security,Shiro 更加简单易用。

shiro基本功能点如下:
shiro基本功能点
Authentication:身份认证/登录;
Authenrization:授权,即权限验证,验证某个已认证的用户是否拥有某个角色或对某个资源具有某个权限;
Session Manager:会话管理,即用户登录后到退出前就是一次会话,会话可以保存所有信息;
Cryptograpy:加密,保护数据的安全性;
Web Support:Web支持,可以很容易的集成到Web环境;
Caching:缓存,比如用户登录后,其用户信息、角色/权限不必每次查询;
Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次自动登录。

Shiro架构

一. 从外部来看shiro,即从应用程序角度来观察如何使用shiro完成工作:

shiro架构
可以看出:Application Code(应用代码)直接调用的对象是Subject,shiro对外的API核心就是Subject。
Subject:主体,代表了当前“用户”,所有的Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager,具体看源码实现;
SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
Realm:域,shiro从Realm获取安全数据(如用户、角色、权限),可以将Realm看成DataSource,即安全数据源。
一个简单的Shiro应用:
1.应用代码通过Subject来进行认证和授权,Subject内部将委托给SecurityManager来处理;
2.给shiro的SecurityManager注入Realm,SecurityManger将获取到数据与用户数据比较进行判断。

二. 从shiro内部来看shiro的架构,如下图:
这里写图片描述
Subject:主体,应用代码直接交互的对象,代表当前交互的“用户”;
SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher;是 Shiro 的心脏;所有具体的交互都通过 SecurityManager 进行控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
Authenticator:认证器,负责主体认证,可以自定义实现;
Authrizer:授权器,控制用户的访问和操作权限;
Realm:可以有 1 个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等等,需要用户自己实现获取数据;
SessionManager:Shiro 抽象了一个自己的 Session 来管理主体与应用之间交互的数据,可以在JavaSE、Web、EJB等环境使用;
SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD,比如我们想把 Session 保存到数据库,那么可以实现自己的 SessionDAO,通过如 JDBC 写到数据库;比如想把 Session 放到 Memcached 中,可以实现自己的 Memcached SessionDAO;另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能;
CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能
Cryptography:密码模块,Shiro 提供了一些常见的加密组件用于如密码加密 / 解密的。

Shiro简单应用

下载shiro jar包,下载地址https://shiro.apache.org/download.html,同时需要下载日志jar包:
log4j-1.2.17.jar
slf4j-api.1.6.1.jar
slf4j-log4j12-1.6.1.jar
maven配置如下:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>

创建一个简单的java工程,在src目录下创建一个配置文件shiro.ini。

规则:[users]用户=密码,角色1,角色2,……..
[roles] 角色=资源:权限…(:实例),资源:权限,…(:实例),……..
roles中可以使用通配符。具体配置如下:

[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz

[roles]
# 所有资源的所有权限
admin = *
# 资源lightsaber的所有权限
schwartz = lightsaber:*
# 资源winnebago的实例eagle5拥有drive权限
goodguy = winnebago:drive:eagle5

创建java类

public class SimpleShiro {
    private static final transient Logger log = LoggerFactory.getLogger(SimpleShiro.class);

    public static void main(String[] args) {

        //读取配置文件,创建SecurityManager工厂,通过工厂创建SecurityManager对象
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        //将SecurityManager绑定到SecurityUtils,一个简单的shiro环境就建好了
        SecurityUtils.setSecurityManager(securityManager);

        //获取主体
        Subject currentUser = SecurityUtils.getSubject();

        // Do some stuff with a Session (no need for a web or EJB container!!!)
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

        // let's login the current user so we can check against roles and permissions:
        if (!currentUser.isAuthenticated()) {   //判断用户是否已认证
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");  //将用户名和密码绑定到UsernamePasswordToken对象中
            token.setRememberMe(true);      //记住密码
            try {
                currentUser.login(token);       //登录认证,委托给SecurityManager处理
            } catch (UnknownAccountException uae) {     //该用户不存在
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {   //该用户密码错误
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {      //该用户被锁定
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //获取用户名

        //test a role:
        if (currentUser.hasRole("schwartz")) {          //判断用户是否有schwartz角色
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //test a typed permission (not instance-level)
        if (currentUser.isPermitted("lightsaber:weild")) {      //判断用户是否有lightsaber:weild权限
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //a (very powerful) Instance Level permission:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {  //判断用户是否有操作eagle5的winnebago:driven权限
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //all done - log out!
        currentUser.logout();       //登出

        System.exit(0);
    }
}
  • 首先通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个SecurityManager 工厂;接着获取 SecurityManager 并绑定到 SecurityUtils,这是一个全局设置,设置一次即可;
  • 通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程(TreadContext);如果在 web环境在请求结束时需要解除绑定;然后获取身份验证的 Token,如用户名 / 密码;
  • 调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login方法进行登录;
  • 如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如:
    DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException(错误的凭证)、ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系;对于页面的错误消息展示,最好使用如“用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
  • 最后可以调用 subject.logout 退出,其会自动委托给 SecurityManager.logout 方法退出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园2.0是高校信息化建设的新阶段,它面对着外部环境变化和内生动力的双重影响。国家战略要求和信息技术的快速发展,如云计算、大数据、物联网等,为智慧校园建设提供了机遇,同时也带来了挑战。智慧校园2.0强调以服务至上的办学理念,推动了教育模式的创新,并对传统人才培养模式产生了重大影响。 智慧校园建设的解决之道是构建一个开放、共享的信息化生态系统,利用互联网思维,打造柔性灵活的基础设施和强大的基础服务能力。这种生态系统支持快速迭代的开发和持续运营交付能力,同时注重用户体验,推动服务创新和管理变革。智慧校园的核心思想是“大平台+微应用+开放生态”,通过解耦、重构和统一运维监控,实现服务复用和深度融合,促进业务的快速迭代和自我演化。 智慧校园的总体框架包括多端协同,即“端”,它强调以人为中心,全面感知和捕获行为数据。这涉及到智能感知设备、超级APP、校园融合门户等,实现一“码”或“脸”通行,提供线上线下服务端的无缝连接。此外,中台战略是智慧校园建设的关键,包括业务中台和数据中台,它们支持教育资源域、教学服务域等多个领域,实现业务的深度融合和数据的全面治理。 在技术层面,智慧校园的建设需要分期进行,逐步解耦应用,优先发展轻量级应用,并逐步覆盖更多业务场景。技术升级路径包括业务数据化、数据业务化、校园设施智联化等,利用IoT/5G等技术实现设备的泛在互联,并通过人工智能与物联网技术的结合,建设智联网。这将有助于实现线上线下一网通办,提升校园安全学习生活体验,同时支持人才培养改革和后勤管理的精细化。 智慧校园的建设不仅仅是技术的升级,更是对教育模式和管理方式的全面革新。通过构建开放、共享的信息化生态系统,智慧校园能够更好地适应快速变化的教育需求,提供更加个性化和高效的服务,推动教育创新和人才培养的高质量发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值