Shiro是一个java安全框架
有三个核心组件:Subject,SecurityManager,Realms.
- Subject
即“当前操作用户”。在Spring中,Subject这一个概念并不仅仅指人,也可以是第三方进程、后台账户(Daemon Account)或其他类似事务。它仅仅意味着“当前跟软件交互的东西”。一般情况下,我们把它理解为Shiro的“用户”。
subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
- SecurityManager
它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
- Realm
Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
以上是百度关于Shiro的定义,接下来我们再看看官网是怎么定义的。
Apache Shiro是一个功能强大且易于使用的java安全框架,可进行认证、授权、加密、session管理以及确保从命令行程序、移动程序到大型网站和企业的任何应用程序。
Shiro提供了应用安全的API来执行以下几个方面:
身份验证 — 证明用户身份,通常称为用户“登录”。
授权 — 访问控制
加密 — 保护或隐藏窥探的数据
session管理 — 每个用户时间敏感状态
Shiro还提供了一些辅助功能,如Web应用安全,单元测试,和多线程的支持,但这些的存在用于强化以上四个主要问题。
在过去,java开发人员对于安全没有很多常用的选择,特别是java的认证和授权服务,有一个叫做JAAS的。JAAS有很多的缺点,其认证能力本就有所欠缺,授权方面的使用更让人扎心。另外,JAAS严重绑在虚拟机级别的安全问题,例如,确定一个类是否应该允许被加载到JVM。作为程序员,我们更关心应用程序最终用户能做什么,而不是我的代码在JVM中能做什么。
在开发中,或许需要一个容器,需要一些可以从容器中分离出来的东西,可以在我选择的任何环境中使用。
最后,还有密码学(加密)的问题。这是一个我们都需要保持数据安全的时代,但java加密体系非常难以理解,除非你是一个密码专家。这个API充满了检查过的异常,觉得使用起来很麻烦。我们希望有一个更干净的解决方案,以便在必要时轻松地加密和解密数据。
因此,Shiro诞生了。
Shiro:易使用,综合,灵活,可插拔,Web,提供支持和服务
Shiro和其前身JSecurity多年来已在各种规模和各种行业的公司的项目中使用。自从成为Apache软件协会的顶级项目以来,网站流量和采用率一直在显著增长。许多开源社区都在使用Shiro,例如,Spring, Grails, Wicket, Tapestry, Tynamo, Mule, 和 Vaadin,这只是仅举几例。
商业企业如Katasoft,Sonatype,MuleSoft,主要的社会网络之一,以及更多的纽约商业银行利用Shiro来保护他们的商业软件和网站。
Subject, SecurityManager, 和Realms
当你保护你的程序时,可能问自己最相关的问题是:“当前用户是谁?”或者“当前用户允许做某件事”吗?
在编写代码或设计用户界面时,我们常常问自己这些问题:应用通常是基于用户层构建的,并且希望基于每个用户的基础来表示(并有安全性)的功能。因此,我们在应用程序中考虑安全性的最自然方式是基于当前用户。Shiro的API用Subject概念根本上体现了这个思想的方式。
Subject 是一个安全术语,基本上是指“当前执行的用户”。它不被称作“用户”,因为“用户”这个词通常跟人有关,在安全领域里,subject可以代表人类,也可以是第三方进程、后台账户(Daemon Account)或其他类似事务。它仅仅意味着“当前跟软件交互的东西”。一般情况下,我们把它理解为Shiro的“用户”。你可以获得Shiro的Subject如下所示。
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser = SecurityUtils.getSubject();
一旦你获取了Subject,你立即获得90%的权限去做一切你想用Shiro为当前用户做的工作,如登录、登出,访问他们的会话,执行授权检查,和更多。
重点是Shiro的API非常直观,因为它反映了开发者在考虑“每个用户”的安全控制时的意向。在代码中任何地方都很容易访问subject,允许在需要的地方进行安全操作。
Subjest的“后台”对应物是SecurityManager。subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
引用了多个内部嵌套的安全组件,构成一个对象图,这是Shiro建筑的心脏和充当“保护伞”的对象。然而,一旦SecurityManager要和其内部的对象图配置好了,它通常是单独离开,并且开发者会花大量时间在SubjectAPI上。
如何建立一个SucurityManager取决于你的应用环境,例如:
一个Web应用程序通常会在web.xml 中指定一个Shiro Servlet过滤器,并将建立SecurityManager实例。如果你正在运行一个独立的应用程序,你需要用另一种方式来配置它。但是有很多配置选项。
几乎每个应用程序总是有一个SecurityManager实例。它本质上是一个应用程序单例(尽管它不需要是静态的单例)。在Shiro里,默认的SecurityManager的实现是POJO和用POJO兼容的可配置的机制 — 正常的java代码,Spring XML,YAML,.properties和.ini文件等。基本的东西是可实例化的类和调用JavaBean兼容的方法可用于。基本的东西是可实例化的类和调用JavaBean兼容的方法。
为此,Shiro通过基于文本的INI配置提供了一个默认的“共同点”的解决方案。INI易于阅读,使用简单,只需要很少的依赖项。
基本介绍见前面介绍的,同百度中给出的一样。
也就是“登录”,主要有三个步骤
1. 收集用户的标识信息,称为主体,并支持身份证明,称为凭据。
2. 向系统提供主题和凭据。
3. 如果提交的凭据与系统期望的用户标识(主体)相符,则用户被认为是经过身份验证的。如果它们不匹配,则不考虑用户身份验证。
最常见的例子就是 用户名和密码的组合。
通过authenticationtoken实例提交主体和凭据(在这种情况下,一个用户名和密码)。
//1. Acquire submitted principals and credentials:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
//2. Get the current Subject:
Subject currentUser = SecurityUtils.getSubject();
//3. Login:
currentUser.login(token);
当登录方法被调用时,SecurityManager将收到的authenticationtoken和分派给一个或多个配置的Realms,要求认证时让每个执行检查。每个Realms有authenticationtokens提交必要的反应能力。但如果登录尝试失败时会发生什么?如果用户指定了一个错误的密码?你可以通过Shiro的运行authenticationexception反应处理故障。
//3. Login:
try {
currentUser.login(token);
} catch (IncorrectCredentialsException ice) { …
} catch (LockedAccountException lae) { …
}
…
catch (AuthenticationException ae) {…
}
你可以选择捕获authenticationexception的子类之一并明确的进行操作,通常我们是处理authenticationexception(例如,向用户显示一个通用的“用户名或密码错误”消息)。
在一个Project成功登录之后,它们被认为是经过验证的,并且通常允许它们使用应用程序。
但仅仅因为用户证明了他们的身份并不意味着他们可以在你的应用程序中为所欲为。这就引出了下一个问题,“我该如何控制用户允许做什么呢?”决定用户允许做什么叫做授权。
授权本质上是访问控制——控制用户在应用程序中可以访问的内容,如资源、Web页面等。大多数用户通过使用诸如角色和权限等概念来执行访问控制。也就是说,用户通常被允许做一些事情,而不是基于分配给他们的角色和/或权限。然后,应用程序可以基于对这些角色和权限的检查来控制哪些功能被公开。下面的代码片段展示了如何检查某个主题是否被指派了某个角色。
if ( subject.hasRole(“administrator”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}
权限检查是执行授权的另一种方式。检查上面示例中的角色有一个重大缺陷:您不能在运行时添加或删除角色。您的代码被硬编码为角色名称,因此如果您更改了角色名称和/或配置,您的代码将被破坏!如果需要在运行时更改角色的含义,或者按照需要添加或删除角色,则必须依赖其他东西。
为此,Shiro支持权限(permission)的概念。通过让权限反映应用程序的原始功能,在更改应用程序功能时,只需要更改权限检查。反过来,您可以在运行时为角色或用户分配权限。下面的例子里,我们可以重写我们以前的角色检查,而不是使用权限检查。
if ( subject.isPermitted(“user:create”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}
这样,分配给用户“user:create”权限的任何角色或用户都可以单击“创建用户”按钮,这些角色和任务甚至可以在运行时更改,为您提供一个非常灵活的安全模型。
“user:create”字符串是一个遵守某些解析约定的权限字符串的示例。
Shiro支持WildcardPermission的相关协议。虽然超出了介绍文章的范围,你会发现wildcardpermission在创建安全策略时可以非常灵活,甚至支持像实例级访问控制
if ( subject.isPermitted(“user:delete:jsmith”) ) {
//delete the ‘jsmith’ user
} else {
//don’t delete ‘jsmith’
}
Shiro提供了一个持续型的Session API,它可以用于所有的程序和所有的建筑层。那就是说,Shiro提供一个Session程序样式 ——— 从小型后台独立应用到大型集群的Web都能使用。意味着开发者不再需要使用Servlet或EJB容器。或者,如果使用这些容器,开发人员现在可以在任何层使用统一一致的会话API,而不是servlet或EJB特定的机制。
但是Shiro Session最好的一个优点是:容器独立。
另一个优点是:session数据能在客户端进行共享。
加密是隐藏或混淆数据以窥视的眼睛不理解的过程。Shiro的目标是简化和使用获得JDK的加密支持。
给Web应用设置一个Shiro很简单。唯一必要的是在web.xml定义Shiro Servlet过滤器。
<filter>
<filter-name>ShiroFilterfilter-name>
<filter-class>
org.apache.shiro.web.servlet.IniShiroFilter
filter-class>
filter>
<filter-mapping>
<filter-name>ShiroFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
Shiro也提供一个JSP标签库
<%@ taglib prefix="shiro"
uri="http://shiro.apache.org/tags" %>
...
<p>Hello
<shiro:user>
<shiro:principal/>!
shiro:user>
<shiro:guest>
! <a href=”register.jsp”>Register today!a>
shiro:guest>
p>
如果用户登陆了显示Hello
,否则显示Hello! Register Today!”
更改的信息可以查看web 文档
点击进入Shiro下载页
如有不明白的地方,可以查看[官网的文档]