Apache Shiro 10分钟教程
介绍
看完这个10分钟入门之后,你就知道如何在你的应用程序中引入和使用Shiro。以后你再在自己的应用程序中使用Shiro,也应该可以在10分钟内搞定。
概述
什么是Apache Shiro?
Apache Shiro是一个功能强大且易于使用的Java安全框架,它为开发人员提供了一种直观,全面的身份验证,授权,加密和会话管理解决方案。
实际上,它可以管理应用程序安全性的所有方面,同时尽可能避免干扰。它建立在可靠的界面驱动设计和OO原则的基础上,可在您可以想象的任何地方实现自定义行为。但是,由于所有内容都具有合理的默认值,因此它可以像应用程序安全性一样“轻松”。至少这就是我们所追求的。
Apache Shiro可以做什么?
很多
注意
Shiro可以在任何环境中运行,从最简单的命令行应用程序到最大的企业Web和集群应用程序,但是对于此QuickStart,我们将在简单的
main
方法中使用最简单的示例,以便您可以快速了解API。
下载
确保已安装JDK 1.6+和Maven 3.0.3+。
从下载页面下载最新的“源代码分发” 。在此示例中,我们使用1.4.2版本。
解压源码包:
1 | $ unzip shiro-root-1.4.2-source-release.zip |
进入quickstart目录:
1 | $ cd shiro-root-1.4.2/samples/quickstart |
运行:
1 | $ mvn compile exec:java |
该目标只会打印一些日志消息,让您知道发生了什么,然后退出。
在看本入门文档的过程中,可以打开源文件samples/quickstart/src/main/java/Quickstart.java
,并且随意修改以测试你的想法。
QuickStart.java
下面我们来分解说明Quickstart.java内的源码以便你可以更好的理解。
在任何环境下你都可以通过如下代码来获取当前登录的用户。
1 | Subject currentUser =SecurityUtils.getSubject(); |
所谓Subject其实就是其他系统中的User,这里只是换一个说法,因为能够登录系统的不仅仅是人,还有其他系统。
如果是在一个独立的应用程序中调用getSubject(),我们会得到一个应用程序本地登录的用户信息,如果是一个web应用,则会得到一个和当前线程或者当前的session相关的用户。
不管怎么样,现在你得到了一个用户了,接下来可以做什么呢?
如果你想要让某些数据在当前用户登录会话期间内一直有效,则可以像下面这么做:
1 | Session session = currentUser.getSession(); |
我们可以把这个Session当成是HttpSession在Shiro中的特殊实现,他和HttpSession有着相似的接口,大家用起来不会陌生。但是他还有一个额外的好处:不依赖于HTTP的上下文环境。这样你就可以在一个非web应用(比如类似于本例子的命令行程序)中使用Session了。
如果是在一个Web应用程序中使用Session,则返回的Session是一种基于HttpSession的实现;而如果是在一个非web环境下使用,则默认使用的是Enterprise Session。不管怎么样,这意味着我们不用理会应用程序的部署环境,总是使用相同的API来操作session,带来一致的用户体验。现在,web应用和非web应用可以共享session数据了。
到目前为止,我们得到了一个Subject以及他的Session,现在我们用它们来做点有实际意义的事情怎么样,比如检查一下这个用户是否有权限做某件事情?
我们可以为一个已知的用户做这些检查。我们上文中的Subject代表着当前用户,但是截至目前来说,谁是当前用户呢?在真正登录之前,Subject表示的是一个匿名用户。下面让我们来看看登录怎么做。
1 | if ( !currentUser.isAuthenticated() ) { |
就这样,简单的不能再简单了。
但是如果登录失败了怎么办?你可以通过捕获异常来准确了解到底发生了什么错误,然后针对性的做一些处理。
1 | try { |
你可以检测很多种不同类型的异常,或者你也可以抛出自己的异常。可以 AuthenticationException JavaDoc去了解更多。
好了,到目前为止,我们有了一个已经登录的用户,然后我们还可以做些什么呢?
比如我们可以打印一些信息来说明我们是谁:
1 | //print their identifying principal (in this case, a username): |
我们也可以测试一下看当前用户是否拥有某个角色。
1 | if ( currentUser.hasRole( "schwartz" ) ) { |
又或者我们可以看看他是否有权限去执行针对某种数据的某种操作。
1 | if ( currentUser.isPermitted( "lightsaber:weild" ) ) { |
我们还可以做一个实例级别的权限检查——看看该用户是否有权限访问某种类型数据的某个具体实例。
1 | if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) { |
真是小菜一碟,不是吗?
最后,如果该用户已经做完了所有的事情,他就可以退出登录了。
1 | currentUser.logout(); //removes all identifying information and invalidates their session too. |
好了,如果我们要在应用程序中使用Apache Shiro,了解以上这些API也就差不都了。虽然在这些优雅的代码下面隐藏了一些复杂的实现。但是对于使用者来说,真的这样就够了。
不过你可能会问你自己:“在用户登录的时候,谁来负责获取用户相关的数据呢(比如用户名、密码、角色、权限等),并且在运行时谁来真正的执行这些安全检查?”,我只能说,是你是你都是你,你要实现一种自Shiro中曾作Realm的接口,并且把它继承到Shiro的配置中。
但是,如何配置Realm主要和你的运行时环境有关。比如,你可能运行的是一个独立的应用、或者而是一个web应用、或者是一个依赖于spring或者JEE容器的的应用,或者是以上几种类型的组合。对于一个10分钟入门来说,以上的这些配置都太复杂了,本节的主要目的是带你熟悉一下Shiro的API以及相关的一些概念。