您的位置:首页 > 其它

我的shiro之旅:自定义filter

2016-06-23 16:46 387 查看
1. shiro的filter介绍

Filter
Name
Class
anonorg.apache.shiro.web.filter.authc.AnonymousFilter
authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logoutorg.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreationorg.apache.shiro.web.filter.session.NoSessionCreationFilter
permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
portorg.apache.shiro.web.filter.authz.PortFilter
restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter
sslorg.apache.shiro.web.filter.authz.SslFilter
userorg.apache.shiro.web.filter.authc.UserFilter
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

<property name="securityManager" ref="securityManager" />

<property name="loginUrl" value="/login" />

<property name="successUrl" value="/home" />

<property name="unauthorizedUrl" value="/unauthorized" />

<!-- filters一般不需要定义,除非自定义filter覆盖原来的时候,需要定义 -->

<!-- <property name="filters">

<map>

<entry key="authc">

<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />

</entry>

</map>

</property> -->

<property name="filterChainDefinitions">

<value>

/admin = authc,roles[admin]

/edit = authc,perms[admin:edit]

/home = user

/** = anon

</value>

</property>

</bean>

loginUrl: 当用户没有登录的时候,会重发一个login请求,引导用户去登录

successUrl:是当用户登录成功,转发home请求

unauthorizedUrl指如果请求失败,重发/unauthorized请求,引导用户到认证异常错误页面

如我们在filterChainDefinitions里配置了/admin=authc,roles[admin],那么/admin这个请求会由org.apache.shiro.web.filter.authc.FormAuthenticationFilter和org.apache.shiro.web.filter.authz.RolesAuthorizationFilter这两个filter来处理,其中authc,roles只是filter的别名。如要更改别名,可以通过filters来改变。如上面的配置

<property
name="filters">

<map>

<entry key="authc">

<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />

</entry>

</map>

</property>

把PassThruAuthenticationFilter添加别名为authc,这时/admin请求会交给PassThruAuthenticationFilter处理,替换了原来由FormAuthenticationFilter来处理。

由此一来,如果有些特殊的请求需要特殊处理,就可以自己写一个filter,添加一个别名,如:

<property
name="filters">

<map>

<entry key="new">

<bean class="com.text.newFilter" />

</entry>

</map>

</property>

2. shiro自定义filter

使用shiro的时候,比较常用的filter有anon,authc,roles和perms。当我们想定义某个链接是拥有某些权限的用户才可以访问的时候,我们可以这样定义。/xx
= roles[A,B]。在shiro中,表示当前用户同时拥有A,B两种角色才可以访问/xx这个链接,是一种&&(与)的关系





RolesAuthorizationFilter这样一个类,这个类就是定义roles的filter。

01
public
class
RolesAuthorizationFilter
extends
AuthorizationFilter
{
02
03
//TODO
- complete JavaDoc
04
05
@SuppressWarnings
({
"unchecked"
})
06
public
boolean
isAccessAllowed(ServletRequest
request, ServletResponse response, Object mappedValue)
throws
IOException
{
07
08
Subject
subject = getSubject(request, response);
09
String[]
rolesArray = (String[]) mappedValue;
10
11
if
(rolesArray
==
null
||
rolesArray.length ==
0
)
{
12
//no
roles specified, so nothing to check - allow access.
13
return
true
;
14
}
15
16
Set<String>
roles = CollectionUtils.asSet(rolesArray);
17
return
subject.hasAllRoles(roles);
18
}
19
20
}
上面定义了subject.hasAllRoles(roles);就是当前用户必须拥有定义的所有角色才会返回true。但有时候,我们需要当前用户拥有定义的其他一个角色就可以访问,那就需要写自己的filter。也很简单,代码以下:

01
public
class
AnyRolesAuthorizationFilter
extends
AuthorizationFilter
{
02
03
 
04
@Override
05
protected
boolean
isAccessAllowed(ServletRequest
request, ServletResponse response, Object mappedValue)
throws
Exception
{
06
07
Subject
subject = getSubject(request, response);
08
String[]
rolesArray = (String[]) mappedValue;
09
10
if
(rolesArray
==
null
||
rolesArray.length ==
0
)
{
11
//
no roles specified, so nothing to check - allow access.
12
return
true
;
13
}
14
15
Set<String>
roles = CollectionUtils.asSet(rolesArray);
16
for
(String
role : roles) {
17
if
(subject.hasRole(role))
{
18
return
true
;
19
}
20
}
21
return
false
;
22
}
23
24
}
从上面的代码可以看到,当遍历,发现当前用户拥有定义的其中一个角色就立刻返回true,否则返回false。

定义好filter,只需要代码默认的roles即可。

01
<
bean
id
=
"shiroFilter"
class
=
"org.apache.shiro.spring.web.ShiroFilterFactoryBean"
>
02
<
property
name
=
"securityManager"
ref
=
"securityManager"
/>
03
<
property
name
=
"loginUrl"
value
=
"/security/login.html"
/>
04
<
property
name
=
"successUrl"
value
=
"/home.html"
/>
05
<
property
name
=
"unauthorizedUrl"
value
=
"/security/unauthorized.html"
/>
06
<
property
name
=
"filters"
>
07
<
map
>
08
<
entry
key
=
"anyRoles"
value-ref
=
"anyRolesAuthorizationFilter"
/>
09
</
map
>
10
</
property
>
11
<
property
name
=
"filterChainDefinitions"
>
12
<
value
>
13
/admin
= anyRoles[admin1,admin2]
14
/**
= anon
15
</
value
>
16
</
property
>
17
</
bean
>
perms的filter也同理。看看源码:

01
public
class PermissionsAuthorizationFilter extends AuthorizationFilter {
02
03
//TODO
- complete JavaDoc
04
05
public
boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
06
07
Subject
subject = getSubject(request, response);
08
String[]
perms = (String[]) mappedValue;
09
10
boolean
isPermitted = true;
11
if
(perms != null && perms.length > 0) {
12
if
(perms.length == 1) {
13
if
(!subject.isPermitted(perms[0])) {
14
isPermitted
= false;
15
}
16
}
else {
17
if
(!subject.isPermittedAll(perms)) {
18
isPermitted
= false;
19
}
20
}
21
}
22
23
return
isPermitted;
24
}
25
}
自定义的filter:

01
public
class
AnyPermissionsAuthorizationFilter
extends
AuthorizationFilter
{
02
03
@Override
04
protected
boolean
isAccessAllowed(ServletRequest
request, ServletResponse response, Object mappedValue)
throws
Exception
{
05
Subject
subject = getSubject(request, response);
06
String[]
perms = (String[]) mappedValue;
07
08
for
(String
perm : perms) {
09
if
(subject.isPermitted(perm))
{
10
return
true
;
11
}
12
}
13
 
14
return
false
;
15
}
16
17
}
配置使用自定义filter

01
<
bean
id
=
"shiroFilter"
class
=
"org.apache.shiro.spring.web.ShiroFilterFactoryBean"
>
02
<
property
name
=
"securityManager"
ref
=
"securityManager"
/>
03
<
property
name
=
"loginUrl"
value
=
"/security/login.html"
/>
04
<
property
name
=
"successUrl"
value
=
"/home.html"
/>
05
<
property
name
=
"unauthorizedUrl"
value
=
"/security/unauthorized.html"
/>
06
<
property
name
=
"filters"
>
07
<
map
>
08
<
entry
key
=
"anyPerms"
value-ref
=
"anyPermissionsAuthorizationFilter"
/>
09
</
map
>
10
</
property
>
11
 
12
<
value
>
13
/admin/add
= anyPerms["admin:delete","admin:add"]
14
/**
= anon
15
</
value
>
16
</
property
>
17
</
bean
>
当用户请求/admin/add时,就会调用自定义的AnyPermissionsAuthorizationFilter来执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: