说了这么些,那我们到底应该如何来实现这个ObjectDefinitionSource接口呢?
首先还是说说Acegi Seucrity 1.x
版本,org.acegisecurity.intercept.web
和org.acegisecurity.intercept.method
包下AbstractFilterInvocationDefinitionSource
和AbstractMethodDefinitionSource
两个抽象类,这两个类分别实现了FilterInvocationDefinitionSource
和MethodDefinitionSource
接口,而这两个接口都继承自ObjectDefinitionSource接口并实现了其中的方法。两个抽象类都使用方法模板模式来实现,将具体的实现方法交给了子类。
提示:
两个抽象类实现了各自接口的 getAttributes(Object object)
方法并在此方法中调用lookupAttributes
(Method
method)
方法,而实际该方法在抽象类中并没有具体的实现,而是留给了子类去实现。 |
|
在Acegi Seucrity
1.x版本中,系统为我们提供了默认的实现,MethodDefinitionMap
类用于返回方法的权限信息,而PathBasedFilterInvocationDefinitionMap
类和RegExpBasedFilterInvocationDefinitionMap
类用于返回URL资源对应的权限信息,也就是ConfigAttributeDefinition对象,现在也许明白一点儿了吧,我们只要按照这三个类的实现方式(也就是”模仿”,从后面的代码中你可以看到)从数据库中获取用户信息和权限信息然后封装成一个ConfigAttributeDefinition
对象返回即可(其实就是一个List列表,前面已经介绍过了),相信通过Hibernate从数据库中获取一个列表应该是再容易不过的了。
回到Spring Security
,系统为我们提供的默认实现有些变化,DefaultFilterInvocationDefinitionSource
和DelegatingMethodDefinitionSource
两个类,从名字也可以看出来它们分别是干什么的了。这两个类分别实现了FilterInvocationDefinitionSource
和MethodDefinitionSource
接口,而这两个接口都继承自ObjectDefinitionSource接口并实现了其中的方法,这和1.x版本中一样。它们都是从配置文件中得到资源和相应权限的信息。
通过上面的介绍,你或许更名白了一些,那我们下面要做的就是实现系统的FilterInvocationDefinitionSource
和MethodDefinitionSource
接口,只是数据源不是从配置文件中读取配置信息是数据库而已。
我们这里对比着
Acegi Seucrity 1.x
版本中的实现,我个人认为它更好理解,还是请你好好看看源代码。
1
自定义FilterInvocationDefinitionSource
在2.0中,系统没有在系统抽象类,所以我们还是使用1.x中的实现方式,首先通过一个抽象类来实现
ObjectDefinitionSource
接口。代码如下:
<!----> 1
public
ConfigAttributeDefinition getAttributes(Object object)
2
3
throws
IllegalArgumentException {
4
5
if
(object
==
null
||
!
(
this
.supports(object.getClass()))) {
6
7
thrownew IllegalArgumentException(
"
Object must be a FilterInvocation
"
);
8
9
}
10
11
String url
=
((FilterInvocation)object).getRequestUrl();
12
13
returnthis.lookupAttributes(url);
14
15
}
16
17
publicabstract ConfigAttributeDefinition lookupAttributes(String url);
18
19
@SuppressWarnings(
"
unchecked
"
)
20
21
publicabstract Collection getConfigAttributeDefinitions();
22
23
@SuppressWarnings(
"
unchecked
"
)
24
25
publicboolean supports(Class clazz) {
26
27
return
FilterInvocation.
class
.isAssignableFrom(clazz);
28
29
}
这段代码你也可以在1.0中找到,getAttributes
方法的入口参数是一个Object对象,这是由系统传给我们的,因为是URL资源的请求,所有可以将这个Object对象强制转换为
FilterInvocation
对象,并通过调用它的getRequestUrl()
方法来获取用户当前请求的URL地址,然后调用子类需要实现的lookupAttributes
方法并将该URL地址作为参数传给该方法,下面是具体的实现类DataBaseFilterInvocationDefinitionSource
类的代码,也就是我们需要实现抽象父类的lookupAttributes方法:
<!----> 1
@Override
2
3
public
ConfigAttributeDefinition lookupAttributes(String url) {
4
5
//
TODO Auto-generated method stub
6
7
//
初始化数据,从数据库读取
8
9
cacheManager.initResourceInCache();
10
11
if
(isUseAntPath()) {
12
13
int
firstQuestionMarkIndex
=
url.lastIndexOf(
"
?
"
);
14
15
if
(firstQuestionMarkIndex
!=
-
1
) {
16
17
url
=
url.substring(
0
, firstQuestionMarkIndex);
18
19
}
20
21
}
22
23
//
将URL在比较前都转换为小写
24
25
if
(isConvertUrlToLowercaseBeforeComprison()) {
26
27
url
=
url.toLowerCase();
28
29
}
30
31
//
获取所有的URL
32
33
List
<
String
>
urls
=
cacheManager.getUrlResources();
34
35
//
倒叙排序--如果不进行排序,如果用户使用浏览器的导航工具访问页面可能出现问题
36
37
//
例如:访问被拒绝后用户刷新页面
38
39
Collections.sort(urls);
40
41
Collections.reverse(urls);
42
43
GrantedAuthority[] authorities
=
new
GrantedAuthority[
0
];
44
45
//
将请求的URL与配置的URL资源进行匹配,并将正确匹配的URL资源对应的权限
46
47
//
取出
48
49
for
(String resourceName_url : urls) {
50
51
boolean
matched
=
false
;
52
53
//
使用ant匹配URL
54
55
if
(isUseAntPath()) {
56
57
matched
=
pathMatcher.match(resourceName_url, url);
58
59
}
else
{
//
perl5编译URL
60
61
Pattern compliedPattern
=
null
;
62
63
Perl5Compiler compiler
=
new
Perl5Compiler();
64
65
try
{
66
67
compliedPattern
=
compiler.compile(resourceName_url, Perl5Compiler.READ_ONLY_MASK);
68
69
}
catch
(MalformedPatternException e) {
70
71
e.printStackTrace();
72
73
}
74
75
matched
=
matcher.matches(url, compliedPattern);
76
77
}
78
79
//
匹配正确,获取响应权限
80
81
if
(matched) {
82
83
//
获取正确匹配URL资源对应的权限
84
85
ResourcDetail detail
=
cacheManager.getResourcDetailFromCache(resourceName_url);
86
87
authorities
=
detail.getAuthorities();
88
89
break
;
90
91
}
92
93
}
94
95
//
将权限封装成ConfigAttributeDefinition对象返回(使用ConfigAttributeEditor)
96
97
if
(authorities.length
>
0
) {
98
99
String authTemp
=
""
;
100
101
for
(GrantedAuthority grantedAuthority : authorities) {
102
103
authTemp
+=
grantedAuthority.getAuthority()
+
"
,
"
;
104
105
}
106
107
String authority
=
authTemp.substring(
0
, (authTemp.length()
-
1
));
108
109
System.out.println(authority);
110
111
ConfigAttributeEditor attributeEditor
=
new
ConfigAttributeEditor();
112
113
attributeEditor.setAsText(authority.trim());
114
115
return
(ConfigAttributeDefinition)attributeEditor.getValue();
116
117
}
118
119
returnnull;
120
121
}
我们这里同样使用了缓存,它参考自系统的UseCache接口的实现,这里不在介绍,你可以查看本例的源代码和系统的实现和本例的配置文件。这里将用户请求的URL地址与从数据库中获取的受保护的URL资源使用
ant
和perl5匹配(这取决与你的配置),如果匹配成功则从缓存中获取访问该资源需要的权限信息,并将其封装成ConfigAttributeDefinition
对象返回,这里使用org.springframework.security.ConfigAttributeEditor
类,该类提供了一个setAsText(String s)
,该方法收取一个字符串作为参数,在该方法中创建ConfigAttributeDefinition
对象并将字符串参数传递给ConfigAttributeDefinition类的构造函数
来初始化该对象。详细的实现还是请你看源代码。现在我们在配置文件添加自己的实现,如下:
<!---->1
<
bean
id
="objectDefinitionSource"
2
class
="org.security.intercept.web.DataBaseFilterInvocationDefinitionSource"
3
p:convertUrlToLowercaseBeforeComprison
="true"
4
p:useAntPath
="true"
5
p:cacheManager-ref
="securityCacheManager"
/>
convertUrlToLowercaseBeforeComprison
属性
定义了在匹配之前将URL都转换为小写,useAntPath属性
定义使用Ant方式匹配URL,cacheManager
属性定义了指向另一个Bean的引用,我们使用它从缓存中获取相应的信息。
2
自定义
MethodDefinitionSource
将方法资源存放在数据库中的实现与
URL资源类似,这里不在累述,下面是
DataBaseMethodInvocationDefinitionSource
的
源代码,读者可以参考注释进行阅读(该类也是继承自一个自定义的抽象类
AbstractMethodDefinitionSource
):
<!----> 1
public
ConfigAttributeDefinition lookupAttributes(Method method, Class targetClass) {
2
3
//
TODO Auto-generated method stub
4
5
//
初始化资源并缓存
6
7
securityCacheManager.initResourceInCache();
8
9
//
获取所有方法资源
10
11
List
<
String
>
methods
=
securityCacheManager.getMethodResources();
12
13
//
权限集合
14
15
Set
<
GrantedAuthority
>
authSet
=
new
HashSet
<
GrantedAuthority
>
();
16
17
//
遍历方法资源,并获取匹配的资源名称,然后从缓存中获取匹配正确
18
19
//
的资源对应的权限(ResourcDetail对象的GrantedAuthority[]对象数据)
20
21
for
(String resourceName_method : methods) {
22
23
if
(isMatch(targetClass, method, resourceName_method)) {
24
25
ResourcDetail detail
=
securityCacheManager.getResourcDetailFromCache(resourceName_method);
26
27
if
(detail
==
null
) {
28
29
break
;
30
31
}
32
33
GrantedAuthority[] authorities
=
detail.getAuthorities();
34
35
if
(authorities
==
null
||
authorities.length
==
0
) {
36
37
break
;
38
39
}
40
41
authSet.addAll(Arrays.asList(authorities));
42
43
}
44
45
}
46
47
if
(authSet.size()
>
0
) {
48
49
String authString
=
""
;
50
51
for
(GrantedAuthority grantedAuthority : authSet) {
52
53
authString
+=
grantedAuthority.getAuthority()
+
"
,
"
;
54
55
}
56
57
String authority
=
authString.substring(
0
, (authString.length()
-
1
));
58
59
System.out.println(
"
>>>>>>>>>>>>>>>
"
+
authority);
60
61
ConfigAttributeEditor attributeEditor
=
new
ConfigAttributeEditor();
62
63
attributeEditor.setAsText(authority.trim());
64
65
return
(ConfigAttributeDefinition)attributeEditor.getValue();
66
67
}
68
69
returnnull;
70
71
}
isMatch
方法用于
对用户当前调用的方法与受保护的方法进行匹配,与URL资源类似,请参考代码。下面是applicationContext-security.xml
文件中的配置,请查看该配置文件。
<!---->1
<
bean
id
="methodDefinitionSource"
2
class
="org.security.intercept.method.DataBaseMethodInvocationDefinitionSource"
3
p:securityCacheManager-ref
="securityCacheManager"
/>
securityCacheManager
属性定义了指向另一个Bean的引用,我们使用它从缓存中获取相应的信息。这个Bean和前一节中介绍的一样。只是这里我们获取的是方法保护定义资源。
分享到:
相关推荐
"springsecurity-namespace"可能指的是Spring Security的XML命名空间配置。在Spring Security的早期版本中,使用XML配置是最常见的实践。例如,你可能会看到以下片段: ```xml **" access="hasRole('ROLE_ADMIN')...
SpringSecurity是Java开发中用于构建安全Web应用的框架,它提供了强大的身份验证、...在学习过程中,分析提供的源代码和示例将有助于深入理解SpringSecurity的工作原理,并能帮助你在实际项目中有效地应用这些知识。
【Spring Security 学习总结】 Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,用于保护基于 Java 的应用程序。本学习总结文档主要针对初学者,旨在剖析一个不安全的应用程序并阐述如何通过 ...
在"Spring Security学习总结一(补命名空间配置)"的文件中,可能涵盖了如何在Spring Security的XML配置中补充命名空间的步骤。命名空间的引入是为了简化配置,例如`<http>`元素用于配置安全拦截和访问规则,`...
SpringSecurity学习总结一.pdf
总结来说,"REST-spring-security"项目展示了如何使用Spring Security来保护RESTful Web服务,包括身份验证、授权、访问控制和安全配置。这个项目可以帮助开发者理解如何在实际应用中实现安全的REST API,确保服务的...
### Spring Security 学习总结 #### 一、Spring Security 概述 Spring Security 是一个功能强大的安全框架,它为基于 Java 的应用程序提供了认证(authentication)和授权(authorization)功能。在 Spring ...
总结,Spring Security 3.1作为一款强大的安全框架,虽然版本较旧,但仍值得开发者深入研究。通过学习和实践,我们可以掌握如何构建安全的Web应用,并理解其背后的原理,为今后的安全开发打下坚实基础。
### Spring Security 概述与应用实践 #### 一、引言 在当今互联网时代,网络安全问题日益凸显,尤其是Web应用程序的...同时,结合实际案例的学习,能够帮助我们更好地理解和掌握Spring Security的核心概念与使用技巧。
总结,Spring Security 3的源码分析是一个深度学习的过程,涵盖了安全领域的多个方面。通过理解其内部工作机制,开发者可以更好地利用这一强大的框架,为应用程序提供安全的保障。同时,源码分析也能帮助开发者解决...
对于初学者,建议从官方文档或教程开始学习,逐步熟悉Spring Security的安装、配置和使用流程。 #### Security命名空间配置 Spring Security通过XML命名空间简化了安全相关的配置。这部分文档详细介绍了如何使用...
spring security 学习总结暑假的时候在学习了Spring安全并成功运用到了项目中。在实践中摸索出了一套结合JSON +智威汤逊(JSON网络令牌)+Spring引导+ Spring Security的技术的权限方案趁着国庆假期记录一下。 内容 ...
### Spring Security3中文教程知识点概览 #### 一、安全核心概念与起步 Spring Security是Spring框架中的一个重要组成部分,主要用于为Web应用提供安全防护。它不仅提供了强大的认证和授权功能,还支持各种加密...
总结起来,"springSecurityTest.zip"文件提供了一个完整的环境,让你可以动手实践Spring Security的基础用法。通过学习其中的代码、笔记和文档,你将理解Spring Security如何与Spring框架协同工作,如何设置认证和...