10 分钟快速上手 Shiro 新手教程

简介: 当前用户现在我们能够开始做一些我们真正关心的事情——执行安全操作。

当前用户

现在我们能够开始做一些我们真正关心的事情——执行安全操作。


当保护我们的应用程序时,我们对自己可能提出的最为相关的问题是“当前用户是谁”或“当前用户是否被允许做XXX”。


当我们编写代码或设计用户接口时,问这些问题是很常见的:应用程序通常是基于用户的背景情况建立的,且你想基于每个用户标准体现(保障)功能。因此,对于我们考虑应用程序安全的最自然的方式是基于当前用户。


Shiro的API使用它的Subject概念从根本上代表了“当前用户”的概念。

几乎在所有的环境中,你可以通过下面的调用获取当前正在执行的用户:

Subject currentUser = SecurityUtils.getSubject();

使用 SecurityUtils.getSubject(),我们可以获得当前正在执行的Subject。Subject是一个安全术语,它基本上的意思是“当前正在执行的用户的特定的安全视图”。它并没有被称为"User"是因为"User"一词通常和人类相关联。


在安全界,术语"Subject"可以表示为人类,而且可是第三方进程,cron job,daemonaccount,或其他类似的东西。它仅仅意味着“该事物目前正与软件交互”。


对于大多数的意图和目的,你可以把 Subject 看成是 Shiro 的"User"概念。


getSubject()在一个独立的应用程序中调用,可以返回一个在应用程序特定位置的基于用户数据的Subject,并且在服务器环境中(例如,Web 应用程序),它获取的Subject 是基于关联了当前线程或传入请求的用户数据的。


当前用户会话

现在你拥有了一个Subject,你能拿它来做什么? 如果你想在应用程序的当前会话中使事物对于用户可用,你可以获得他们的会话:

Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );

Session是一个Shiro的特定实例,它提供了大部分你经常与 HttpSessoins使用的东西,除了一些额外的好处以及一 个巨大的区别:它不需要一个 HTTP 环境!


如果在一个Web应用程序内部部署,默认的Session将会是基于 HttpSession 的。但在一个非 Web 环境中,像这 个简单的教程应用程序,Shiro将会默认自动地使用它的 Enterprise Session Management。这意味着你会使用相同的API在你的应用程序,在任何层,不论部署环境!这开辟了应用程序的新世界,由于任何需要会话的应用程序不必再被强制使用HttpSession或EJB Stateful Session Beans。并且,任何客户端技术现在能够共享会话数据。


因此,现在你能获取一个Subject以及他们的Session。如果他们被允许做某些事,如对角色和权限的检查,像“检查”真正有用的地方在哪呢?


权限检查

嗯,我们只能为一个已知的用户做这些检查。我们上面的 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.");
}

当然,我们可以执行极其强大的实例级权限检查——判断用户是否有能力访问某一类型的特定实例的能力:

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.
相关文章
|
存储 Linux API
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(三)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
345 1
|
算法
Floyd 最短路径【学习算法】
Floyd 最短路径【学习算法】
197 0
|
11月前
|
Java 测试技术 应用服务中间件
Spring Boot 配置文件总结
Spring Boot 提供全局配置文件 `application.properties` 和 `application.yml`,用于修改自动配置的默认值。前者使用键值对配置,后者使用缩进和冒号。不同环境(开发、测试、生产)可切换配置文件,通过 `spring.profiles.active` 指定。例如,开发环境端口为4790,测试环境为4791,生产环境为4792。配置示例展示了属性、List、Map定义及引用方法。
376 14
|
监控 安全 物联网
5G技术的革命性进步及其对社会的影响
5G技术作为移动通信领域的革命性进步,正深刻地影响着我们的生活和社会。它不仅提供了更快的数据传输速率和更低的延迟,还将引领着各个领域的创新和发展。从移动通信、工业、医疗到智能城市,5G技术正在改变着我们的世界,为未来带来更多可能性。然而,我们也需要解决一些挑战,确保5G技术的安全和可持续发展。随着技术的不断进步,5G技术的前景依然充满希望,将为我们的社会带来更多的创新和变革。
1488 1
5G技术的革命性进步及其对社会的影响
|
存储 SQL 分布式计算
Apache Paimon:Streaming Lakehouse is Coming
本文整理自阿里云智能开源表存储负责人,PPMC Member of Paimon,Flink PMC 成员李劲松(花名:之信)、同程旅行大数据专家,Apache Hudi & Paimon Contributor 吴祥平、汽车之家大数据计算平台负责人邸星星、联通数科大数据高级技术专家,Apache Paimon Contributor 王云朋在 Flink Forward Asia 2023 主会场的分享。
1381 1
Apache Paimon:Streaming Lakehouse is Coming
Python 在 Windows 环境下的文件路径问题
在 Python 程序中,我们经常需要对文件进行操作。在 Windows 下,文件目录路径使用反斜杠“\”来分隔。然而,在 Python 代码中,反斜杠“\”是转义符,例如“\n”表示换行符、“\t”表示制表符。这样,如果继续使用“\”表示文件路径,就会产生歧义。
|
存储 数据采集 机器学习/深度学习
数据湖和数据中台
简要介绍数据湖的特点和功能,与数据仓库的区别。此外,还介绍了数据中台的作用和功能。
1248 0
数据湖和数据中台
|
存储 数据处理 数据格式
MOT_Challenge官方代码TrackEval介绍
MOT_Challenge官方代码TrackEval介绍
1423 0
|
存储 安全 数据管理
2.3连接企业存量资产管理系统|学习笔记(一)
快速学习2.3连接企业存量资产管理系统
2.3连接企业存量资产管理系统|学习笔记(一)