转自http://my.oschina.net/heroShane/blog/203271
Shiro权限框架
开发系统中,少不了权限,目前java里的权限框架有SpringSecurity和Shiro(以前叫做jsecurity),对于SpringSecurity:功能太过强大以至于功能比较分散,使用起来也比较复杂,跟Spring结合的比较好。对于初学Spring Security者来说,曲线还是较大,需要深入学习其源码和框架,配置起来也需要费比较大的力气,扩展性也不是特别强。
对于新秀Shiro来说,好评还是比较多的,使用起来比较简单,功能也足够强大,扩展性也较好。听说连Spring的官方都不用Spring Security,用的是Shiro,足见Shiro的优秀。
网上找到两篇介绍:
http://www.infoq.com/cn/articles/apache-shiro
http://www.ibm.com/developerworks/cn/opensource/os-cn-shiro/,
使用和配置起来还是比较简单。下面只是简单介绍下我们是如何配置和使用Shiro的(暂时只用到了Shiro的一部分,没有配置shiro.ini文件)。
首先是添加过滤器,在web.xml中:
1
2
3
4
5
6
7
8
9
10
11
12
|
<
filter
>
<
filter-name
>shiroFilter</
filter-name
>
<
filter-class
>org.springframework.web.filter.DelegatingFilterProxy</
filter-class
>
<
init-param
>
<
param-name
>targetFilterLifecycle</
param-name
>
<
param-value
>true</
param-value
>
</
init-param
>
</
filter
>
<
filter-mapping
>
<
filter-name
>shiroFilter</
filter-name
>
<
url-pattern
>/*</
url-pattern
>
</
filter-mapping
>
|
权限的认证类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public
class
ShiroDbRealm
extends
AuthorizingRealm {
@Inject
private
UserService userService ;
/**
* 认证回调函数,登录时调用.
*/
protected
AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
throws
AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
User user= userService.getUserByUserId(token.getUsername());
if
(user!=
null
) {
return
new
SimpleAuthenticationInfo(user.getUserName()
,user.getPassWord()
,getName());
}
else
{
return
null
;
}
}
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
*/
protected
AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String loginName = (String) principals.fromRealm(getName()).iterator().next();
User user= userService.getUserByUserId(loginName);
if
(user !=
null
) {
SimpleAuthorizationInfo info =
new
SimpleAuthorizationInfo();
info.addStringPermission(
"common-user"
);
return
info;
}
else
{
return
null
;
}
}
}
|
Spring的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
beans
>
<
description
>Shiro Configuration</
description
>
<
bean
class
=
"org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"
/>
<
bean
id
=
"securityManager"
class
=
"org.apache.shiro.web.mgt.DefaultWebSecurityManager"
>
<
property
name
=
"realm"
ref
=
"shiroDbRealm"
/>
</
bean
>
<
bean
id
=
"shiroDbRealm"
class
=
"com.company.service.common.shiro.ShiroDbRealm"
/>
<
bean
id
=
"shiroFilter"
class
=
"org.apache.shiro.spring.web.ShiroFilterFactoryBean"
>
<
property
name
=
"securityManager"
ref
=
"securityManager"
/>
<
property
name
=
"loginUrl"
value
=
"/common/security/login"
/>
<
property
name
=
"successUrl"
value
=
"/common/security/welcome"
/>
<
property
name
=
"unauthorizedUrl"
value
=
"/common/security/unauthorized"
/>
<
property
name
=
"filterChainDefinitions"
>
<
value
>
/resources/** = anon
/manageUsers = perms[user:manage]
</
value
>
</
property
>
</
bean
>
<
bean
id
=
"lifecycleBeanPostProcessor"
class
=
"org.apache.shiro.spring.LifecycleBeanPostProcessor"
/>
<
bean
class
=
"org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on
=
"lifecycleBeanPostProcessor"
/>
<
bean
class
=
"org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"
>
<
property
name
=
"securityManager"
ref
=
"securityManager"
/>
</
bean
>
</
beans
>
|
登录的Controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
@Controller
@RequestMapping
(value =
"/common/security/*"
)
public
class
SecurityController {
@Inject
private
UserService userService;
@RequestMapping
(value =
"/login"
)
public
String login(String loginName, String password,
HttpServletResponse response,
HttpServletRequest request)
throws
Exception {
User user = userService.getUserByLogin(loginName);
if
(
null
!= user) {
setLogin(loginInfoVO.getuserName(), loginInfoVO.getUserId());
return
"redirect:/common/security/welcome"
;
}
else
{
return
"redirect:/common/path?path=showLogin"
;
}
};
public
static
final
void
setLogin(String userName, String password) {
Subject currentUser = SecurityUtils.getSubject();
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(userName, password);
//this is all you have to do to support 'remember me' (no config - built in!):
token.setRememberMe(
true
);
currentUser.login(token);
}
};
@RequestMapping
(value=
"/logout"
)
@ResponseBody
public
void
logout(HttpServletRequest request){
Subject subject = SecurityUtils.getSubject();
if
(subject !=
null
) {
subject.logout();
}
request.getSession().invalidate();
};
}
|
注册和获取当前登录用户:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
static
final
void
setCurrentUser(User user) {
Subject currentUser = SecurityUtils.getSubject();
if
(
null
!= currentUser) {
Session session = currentUser.getSession();
if
(
null
!= session) {
session.setAttribute(Constants.CURRENT_USER, user);
}
}
}
public
static
final
User getCurrentUser() {
Subject currentUser = SecurityUtils.getSubject();
if
(
null
!= currentUser) {
Session session = currentUser.getSession();
if
(
null
!= session) {
User user = (User) session.getAttribute(Constants.CURRENT_USER);
if
(
null
!= user){
return
user;
}
}
}
}
/**
* 清除所有用户授权信息缓存.
*/
public
void
clearAllCachedAuthorizationInfo() {
Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
if
(cache !=
null
) {
for
(Object key : cache.keys()) {
cache.remove(key);
}
}
}
|
需要的jar包有3个:shiro-core.jar,shiro-spring.jar,shiro-web.jar。感觉shiro用起来比SpringSecurity简单很多。