
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
昆明IT培训的老师这一期给大家讲使用Shiro。
现在SecurityManager已经设置好了,我们终于可以做一些真正地与安全相关的操作了、
当我们考虑应用的安全性时,通常会遇到的问题是“当前用户是谁?”,“当前用户可以做什么?”所以,应用的安全性工作主要建立在当前用户之上。在shiro API中用Subject这个含义更广的概念代替当前用户这个概念。
几乎在任何环境中,你都可以通过下述代码获得当前正在执行程序的用户。
Subject currentUser = SecurityUtils.getSubject();
使用SecurityUtils.getSubject方法,我们可以获得当前正在执行程序的Subject。我们并不称之为前正在执行程序的用户,因为用户通常是指人,而Subject可以指人、进程、计划任务、守护进程等。准确的说,Subject指的是“当前和软件交互的事物”。在多数场景中,你可以将Subject粗暴地认为是用户。
在一个独立的程序中,getSubject()函数基于应用内存中的用户数据返回一个Subject,在一个服务器环境中(如web应用),Subject通常是基于与当前进程有关的用户数据或是来到的请求。
既然我们已经有了Subject,我们可以拿它来做什么?
你可以获取当前Session并存储一些东西。
Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );
这里的Session是基于Shiro的,它的功能与HttpSession类似,但是有一个巨大的不同:它不需要HTTP环境!
如果在web应用中部署shiro,则Session默认就是基于HttpSession的。但是在非web应用中,比如本教程,Shiro会自动用它的Enterprise Session Managerment。这样你就可以使用一样的API而不用管部署环境是什么了。
现在昆明IT培训的老师已经获得了Subject和它的Session,那么怎么用这些东西去检测Subject是否具有某权限、某许可呢?
我们只能对当前用户检测这些东西。我们的Subject对象就是当前用户,但是Subject是谁?不知道,它是匿名的,除非它至少登录过一次,否则我们无从得知Subject是谁。所以,我们让Subject登录:
1 if ( !currentUser.isAuthenticated() ) {
2 //collect user principals and credentials in a gui specific manner
3 //such as username/password html form, X509 certificate, OpenID, etc.
4 //We'll use the username/password example here since it is the most common.
5 UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
6
7 //this is all you have to do to support 'remember me' (no config - built in!):
8 token.setRememberMe(true);
9
10 currentUser.login(token);
11 }
现在,Subject已经登录了。
如果登录失败,我们可以捕获异常并且做相应处理。
1 try {
2 currentUser.login( token );
3 //if no exception, that's it, we're done!
4 } catch ( UnknownAccountException uae ) {
5 //username wasn't in the system, show them an error message?
6 } catch ( IncorrectCredentialsException ice ) {
7 //password didn't match, try again?
8 } catch ( LockedAccountException lae ) {
9 //account for that username is locked - can't login. Show them a message?
10 }
11 ... more types exceptions to check if you want ...
12 } catch ( AuthenticationException ae ) {
13 //unexpected condition - error?
14 }
这里有很多不同类型的异常,你也可以自定义自己的异常。
到这一步,我们已经有了一个登录过的用户,我们可以来做些什么呢?
我们来看看它是谁:
//print their identifying principal (in this case, a username):
#( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
我们也可以检测一下它有没有某些角色:
if ( currentUser.hasRole( "schwartz" ) ) {
#("May the Schwartz be with you!" );
} else {
#( "Hello, mere mortal." );
}
我们也可以检测它是否被允许访问某些实体。
if ( currentUser.isPermitted( "lightsaber:weild" ) ) {
#("You may use a lightsaber ring. Use it wisely.");
} else {
#("Sorry, lightsaber rings are for schwartz masters only.");
}
我们也可以进行一些insstance-level(实例级别)的许可检测。即检测用户是否被允许访问某些实例。
if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {
#("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
#("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
最后,用户可以登出系统。
currentUser.logout(); //removes all identifying information and invalidates their session too.