On this page
10 Apache Shiro 的分钟教程
Share |
Introduction
欢迎使用 Apache Shiro 的 10 分钟教程!
通过快速简单的教程,您应该完全了解开发人员如何在其应用程序中使用 Shiro。而且您应该能够在 10 分钟内完成操作。
Overview
什么是 Apache Shiro?
Apache Shiro 是一个功能强大且易于使用的 Java 安全框架,它为开发人员提供了一种直观,全面的身份验证,授权,加密和会话 Management 解决方案。
实际上,它可以 Management 应用程序安全性的所有方面,同时尽可能避免干扰。它构建在可靠的界面驱动设计和 OO 原理之上,可在您可以想象的任何地方实现自定义行为。但是,对于所有内容都使用合理的默认值,它就像应用程序安全性一样“轻松”。至少那是我们所追求的。
Apache Shiro 可以做什么?
很多 。但是我们不想夸大快速入门。如果您想了解它可以为您做什么,请查看我们的Features页面。另外,如果您对我们的起步方式以及我们为什么存在感到好奇,请参阅四郎的历史与使命页。
好。现在让我们实际做些事情!
Note
Shiro 可以在任何环境中运行,从最简单的命令行应用程序到最大的企业 Web 和群集应用程序,但是对于此 QuickStart,我们将在简单的``方法中使用最简单的示例,以便您对 API。
Download
确保已安装 JDK 1.6 和 Maven 3.0.3.
从Download页下载最新的“源代码分发”。在此示例中,我们使用 1.5.3 版本分发。
解压源码包:
$ unzip shiro-root-1.5.3-source-release.zip
- Importing 快速入门目录:
$ cd shiro-root-1.5.3/samples/quickstart
- 运行快速入门:
$ mvn compile exec:java
该目标只会打印一些日志消息,让您知道发生了什么,然后退出。阅读此快速入门时,请随时查看samples/quickstart/src/main/java/Quickstart.java
下的代码。更改该文件,并根据需要多次运行上面的mvn compile exec:java
命令。
Quickstart.java
上面引用的Quickstart.java
文件包含使您熟悉 API 的所有代码。现在让我们在这里将其分解成块,以便您可以轻松了解发生了什么。
在几乎所有环境中,都可以通过以下调用获取当前执行的用户:
Subject currentUser = SecurityUtils.getSubject();
使用SecurityUtils。 getSubject(),我们可以获得当前正在执行的Subject。 * Subject *只是应用程序用户的特定于安全性的“视图”。我们实际上想将其称为“用户”,因为那“很合理”,但我们决定反对:太多的应用程序具有已经具有自己的用户类/框架的现有 API,并且我们不想与它们发生冲突。同样,在安全领域中,术语Subject
实际上是公认的术语。好吧,continue...
独立应用程序中的getSubject()
调用可能会基于特定于应用程序位置的用户数据返回Subject
,而在服务器环境(例如 Web 应用程序)中,它会基于与当前线程或传入请求相关联的用户数据获取Subject
。
现在您有了Subject
,该怎么办?
如果要在用户与应用程序的当前会话期间使事情可用,则可以获取他们的会话:
Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );
Session
是 Shiro 特定的实例,它提供了常规 HttpSession 所使用的大部分功能,但具有一些额外的好处,并且有一个“很大的”区别:它不需要 HTTP 环境!
如果部署在 Web 应用程序中,则默认情况下Session
将基于HttpSession
。但是,在非 Web 环境中,例如简单的快速入门,Shiro 将默认自动使用其企业会话 Management。这意味着无论部署环境如何,您都可以在任何层的应用程序中使用相同的 API。这为应用程序打开了一个全新的世界,因为不需要强制要求会话的任何应用程序使用HttpSession
或 EJB 状态会话 Bean。而且,任何 Client 端技术现在都可以共享会话数据。
因此,现在您可以获得Subject
和他们的Session
。 “true”有用的东西(例如检查是否被允许做事,例如检查角色和权限)呢?
好吧,我们只能对已知用户进行检查。上面的Subject
实例代表当前用户,但是谁是当前用户?好吧,他们是匿名的-也就是说,直到他们至少登录一次。因此,让我们这样做:
if ( !currentUser.isAuthenticated() ) {
//collect user principals and credentials in a gui specific manner
//such as username/password html form, X509 certificate, OpenID, etc.
//We'll use the username/password example here since it is the most common.
//(do you know what movie this is from? ;)
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//this is all you have to do to support 'remember me' (no config - built in!):
token.setRememberMe(true);
currentUser.login(token);
}
而已!再简单不过了。
但是,如果他们的登录尝试失败了怎么办?您可以捕获各种特定的异常,这些异常可以准确地告诉您发生了什么,并允许您进行相应的处理和响应:
try {
currentUser.login( token );
//if no exception, that's it, we're done!
} catch ( UnknownAccountException uae ) {
//username wasn't in the system, show them an error message?
} catch ( IncorrectCredentialsException ice ) {
//password didn't match, try again?
} catch ( LockedAccountException lae ) {
//account for that username is locked - can't login. Show them a message?
}
... more types exceptions to check if you want ...
} catch ( AuthenticationException ae ) {
//unexpected condition - error?
}
您可以检查许多不同类型的异常,也可以针对自定义条件抛出自己的异常,而 Shiro 可能无法解决。有关详情,请参见AuthenticationException JavaDoc。
Handy Hint
安全最佳实践是将通用的登录失败消息发送给用户,因为您不想帮助攻击者尝试闯入您的系统。
好的,到目前为止,我们已经有一个登录用户。我们还能做什么?
假设他们是谁:
//print their identifying principal (in this case, a username):
log.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
我们还可以测试一下它们是否具有特定作用:
if ( currentUser.hasRole( "schwartz" ) ) {
log.info("May the Schwartz be with you!" );
} else {
log.info( "Hello, mere mortal." );
}
我们还可以查看他们是否有权对某种类型的实体采取行动:
if ( currentUser.isPermitted( "lightsaber:weild" ) ) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}
此外,我们可以执行极其强大的* instance-level *权限检查-能够查看用户是否具有访问类型的特定实例的能力:
if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {
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!");
}
小菜一碟吧?
最后,当用户使用完应用程序后,他们可以注销:
currentUser.logout(); //removes all identifying information and invalidates their session too.
嗯,这是在应用程序开发人员级别使用 Apache Shiro 的核心。而且尽管有一些相当复杂的东西在引擎盖下进行,以使这项工作如此优雅,但实际上仅此而已。
但是您可能会问自己:“但是,谁负责在登录期间获取用户数据(用户名和密码,角色和权限等),以及谁在运行时实际执行那些安全检查?”好的,您可以实现 Shiro 所谓的Realm并将Realm
插入 Shiro 的配置中。
但是,如何配置Realm很大程度上取决于您的运行时环境。例如,如果您运行一个独立的应用程序,或者您有一个基于 Web 的应用程序,或者一个基于 Spring 或 JEE 容器的应用程序,或者它们的组合。这种配置类型不在本“快速入门”的范围之内,因为它的目的是使您熟悉 API 和 Shiro 的概念。
当您准备好详细了解一下时,您肯定会想要阅读Authentication Guide和Authorization Guide。然后可以移至其他Documentation,特别是Reference Manual,以回答任何其他问题。您可能还想加入mailing list用户-您会发现我们有一个很棒的社区,其中的人们愿意在可能的情况下提供帮助。
感谢您的关注。我们希望您喜欢使用 Apache Shiro!