Shiro安全框架的一些理论介绍
Apache Shiro 体系结构
Apache Shiro的设计目标就是用直观且易于使用的方式,来简化应用的安全性,Shiro的核心设计是基于在某人(或某物)与应用程序交互的上下文中的
软件应用经常是基于用户故事设计的,也就是说基于用户与软件交互的方式来设计用户界面或服务API,比如在用户登录后给用户展示一个个人信息按钮,用户未登录时展示一个登录按钮。应用程序的代码都是用于满足用户的需求的,即使这个所谓的“用户”是另一个软件系统
Shiro在自己的设计中体现了这些概念,实际上,Apache Shiro在任何应用程序中都保持直观和易于使用的特点
Shiro概述
概括的说,Shiro有3个主要的概念,Subject,SecurityManager和Realms,下图展示了他们之间的关系
ShiroBasicArchitecture.png
Subject:正如之前提到的,Subject是当前执行的用户所拥有的特定于安全的视图,“User”的概念经常和人绑定,而Subject可以使人,也可以是第三方服务,等等与软件交互的任何事务。Subject实例都绑定到SecurityManager,与Subject交互时,这些交互转化为与SecurityManager的特定于Subject的交互。
SecurityManager:SecurityManager是Shiro体系结构的核心,它协调其内部安全组件,形成一个对象图。一旦SecurityManager和它的内部对象图配置完成,通常就不在需要和SecurityManager打交道,开发人员更多的是和Subject 的 API 打交道。之后会详细介绍SecurityManager的细节内容,需要注意的是,Subject上的所有操作,背后都是SecurityManager在进行工作的
Realms
:Realms是Shiro和应用安全数据的桥梁,当需要与用户帐户安全相关的数据进行实际交互以执行身份验证(登录)和授权(访问控制)时,Shiro将会从事先配置好的Realms中获取数据。
Realms相当于安全方面的DAO,它封装了与数据源的连接等细节,为Shiro提供需要的数据。在配置Shiro时,必须至少配置一个Realm用于认证和授权,也就是说,SecurityManager至少需要一个Realm
Shiro提供了一些开箱即用的Realms,来连接各个数据源,如LDAP,关系型数据库,文本文件如INI配置文件等等,如果默认的Realm不能满足需求,也可以实现自己的Realm来自定义数据源
与其他内部组件一样,Shiro的SecurityManager从Realms获取以Subject实例表示的身份数据
详细架构
下图展示了Shiro的具体核心架构
ShiroArchitecture.png
ShiroArchitecture.png
Subject——org.apache.shiro.subject.Subject
特定于当前与软件交互的实体的安全视图
SecurityManager——org.apache.shiro.mgt.SecurityManager
Shiro架构的核心,管理并协调各个组件共同完成安全工作,它还管理每个应用程序用户的Shiro视图,因此它知道如何为每个用户执行安全操作。
Authenticator——org.apache.shiro.authc.Authenticator
Authenticator是负责认证的组件,当用户尝试登录时,登录是由Authenticator来执行的,Authenticator将会从Realms取出用户信息,来和用户提供的登录信息进行比对
Authenticator Strategy——org.apache.shiro.authc.pam.AuthenticationStrategy
如果超过一个Realm被配置了,这个AuthenticationStrategy将会协调这些Realms来决定认证操作是否成功,比如,认证成功是需要所有的Realms都认证成功,还是仅仅一个Realm成功
Authorizer——org.apache.shiro.authz.Authorizer
Authorizer是负责访问控制的组件,换句话说,它负责检测用户是否有执行某个操作的权限。和Authenticator一样,Authorizer也从多个Realms数据源中获取用户的角色信息和权限信息,通过这些信息来判断用户是否可以执行某个操作
SessionManager——org.apache.shiro.session.mgt.SessionManager
注意不是SecurityManager,SessionManager负责创建和管理用户的Session周期。在安全框架中,Shiro提供了一个独有的特性,Shiro可以在任何环境中管理用户会话,即使实在非Web/Servlet和非EJB容器环境中,默认情况下,Shiro将会使用已有的会话机制,如Servlet容器,如果没有,Shiro将会使用内建的企业会话管理机制来管理会话。通过SessionDao,我们可以使用任何数据源来持久化Session
SessionDAO——org.apache.shiro.session.mgt.eis.SessionDAO
SessionDAO代表SessionManager执行会话持久性(CRUD)操作。它允许将任何数据存储插入到Session Management基础结构中
CacheManager——org.apache.shiro.cache.CacheManager
CacheManager负责创建Shiro中的其他组件的Cache实例并管理其生命周期,因为Shiro需要访问各种数据源来进行认证,授权和会话管理,缓存一直是框架中的一流架构特性,可以在使用这些数据源时提高性能,任何现代的开源或者企业缓存产品都可以接入Shiro中
Cryptography——org.apache.shiro.crypto.*
Shiro的crypto包包含了易于使用和理解的常见加密算法实现。使用过Java自带的加密库的人都应该知道它很难使用,Shiro提供的加密API简化了复杂的Java机制,让加密更便于使用
Realms——org.apache.shiro.realm.Realm
正如前面提到的,Realms是Shiro和应用程序数据的桥梁,当需要执行认证和授权时,Shiro会从至少一个Realm中寻找用户信息,应用程序中可以配置许多个Realm,Shiro会在必要时协调这些Realm
SecurityManager
Shiro的API提倡以Subject为中心的编程方式,因此大多数的开发者很少会和SecurityManager直接接触,但是,仍然有必要去了解SecurityManager如何进行工作,尤其是为应用程序配置SecurityManager的时候
SecurityManager 相关设计
SecurityManager主要负责执行安全操作和管理所有应用程序用户的状态,在Shiro的默认视线中,它包括以下功能:
- 认证
- 授权
- 会话管理
- 缓存管理
- 协调Realm
- 事件传播
- “记住我”服务
- 创建Subject
- 登录等等功能
但是在单个组件中要管理的功能太多了。而且,如果所有的东西都集中到一个实现类中,那么使这些东西变得灵活和可定制将是非常困难的。为了简化配置,让配置变得灵活,Shiro进行了高度的模块化实现,即SecurityManager的实现更多是扮演了一个轻量级的容器组件,将所有的行为委托给它拥有的组件、
当组件执行它们的逻辑的时候,SecurityManager知道在何时,如何去协调这些组件以达到正确的行为。SecurityManager的实现和它的组件都是兼容JavaBean的,也就是说,可以通过JavaBean的方式来配置它们,如Spring等等
Shiro安全框架实操部分了解一些代码:
pom.xml的文件依赖
<!-- mybatis整合SpringBoot--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency>
<!--整合包--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
<!-- druids数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.12</version> </dependency>
<!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency>
<!-- MySql的依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>1.2.17</version> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.9.1</version> </dependency>
<!-- Thymeleaf模板--> <!--Thymeleaf 说明基于3.0.1 模板引擎--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> <version>3.0.4.RELEASE</version> </dependency>
log4j文件信息:
<Configuration name="ConfigTest" status="ERROR" monitorInterval="5"> <!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file ~ distributed with this work for additional information ~ regarding copyright ownership. The ASF licenses this file ~ to you under the Apache License, Version 2.0 (the ~ "License"); you may not use this file except in compliance ~ with the License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, ~ software distributed under the License is distributed on an ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ~ KIND, either express or implied. See the License for the ~ specific language governing permissions and limitations ~ under the License. --> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="org.springframework" level="warn" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Logger name="org.apache" level="warn" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Logger name="net.sf.ehcache" level="warn" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Logger name="org.apache.shiro.util.ThreadContext" level="warn" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
shir.inl文件
# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # ============================================================================= # Quickstart INI Realm configuration # # For those that might not understand the references in this file, the # definitions are all based on the classic Mel Brooks' film "Spaceballs". ;) # ============================================================================= # ----------------------------------------------------------------------------- # Users and their assigned roles # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc # ----------------------------------------------------------------------------- [users] # user 'root' with password 'secret' and the 'admin' role root = secret, admin # user 'guest' with the password 'guest' and the 'guest' role guest = guest, guest # user 'presidentskroob' with password '12345' ("That's the same combination on # my luggage!!!" ;)), and role 'president' presidentskroob = 12345, president # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz' darkhelmet = ludicrousspeed, darklord, schwartz # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz' lonestarr = vespa, goodguy, schwartz # ----------------------------------------------------------------------------- # Roles with assigned permissions # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc # ----------------------------------------------------------------------------- [roles] # 'admin' role has all permissions, indicated by the wildcard '*' admin = * # The 'schwartz' role can do anything (*) with any lightsaber: schwartz = lightsaber:* # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with # license plate 'eagle5' (instance specific id) goodguy = winnebago:drive:eagle5
标题