`
FengShen_Xia
  • 浏览: 279418 次
  • 性别: Icon_minigender_1
  • 来自: 东方水城
社区版块
存档分类
最新评论

Spring Security学习总结2_2

阅读更多

说了这么些,那我们到底应该如何来实现这个ObjectDefinitionSource接口呢?

首先还是说说Acegi Seucrity 1.x 版本,org.acegisecurity.intercept.weborg.acegisecurity.intercept.method 包下AbstractFilterInvocationDefinitionSourceAbstractMethodDefinitionSource 两个抽象类,这两个类分别实现了FilterInvocationDefinitionSourceMethodDefinitionSource 接口,而这两个接口都继承自ObjectDefinitionSource接口并实现了其中的方法。两个抽象类都使用方法模板模式来实现,将具体的实现方法交给了子类。

提示:
两个抽象类实现了各自接口的 getAttributes(Object object) 方法并在此方法中调用lookupAttributes
(Method method)
方法,而实际该方法在抽象类中并没有具体的实现,而是留给了子类去实现。
 

在Acegi Seucrity 1.x版本中,系统为我们提供了默认的实现,MethodDefinitionMap 类用于返回方法的权限信息,而PathBasedFilterInvocationDefinitionMap 类和RegExpBasedFilterInvocationDefinitionMap 类用于返回URL资源对应的权限信息,也就是ConfigAttributeDefinition对象,现在也许明白一点儿了吧,我们只要按照这三个类的实现方式(也就是”模仿”,从后面的代码中你可以看到)从数据库中获取用户信息和权限信息然后封装成一个ConfigAttributeDefinition 对象返回即可(其实就是一个List列表,前面已经介绍过了),相信通过Hibernate从数据库中获取一个列表应该是再容易不过的了。

回到Spring Security ,系统为我们提供的默认实现有些变化,DefaultFilterInvocationDefinitionSourceDelegatingMethodDefinitionSource 两个类,从名字也可以看出来它们分别是干什么的了。这两个类分别实现了FilterInvocationDefinitionSourceMethodDefinitionSource 接口,而这两个接口都继承自ObjectDefinitionSource接口并实现了其中的方法,这和1.x版本中一样。它们都是从配置文件中得到资源和相应权限的信息。

通过上面的介绍,你或许更名白了一些,那我们下面要做的就是实现系统的FilterInvocationDefinitionSourceMethodDefinitionSource 接口,只是数据源不是从配置文件中读取配置信息是数据库而已。

我们这里对比着 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和前一节中介绍的一样。只是这里我们获取的是方法保护定义资源。

分享到:
评论

相关推荐

    Spring Security 学习总结1_3

    "springsecurity-namespace"可能指的是Spring Security的XML命名空间配置。在Spring Security的早期版本中,使用XML配置是最常见的实践。例如,你可能会看到以下片段: ```xml **" access="hasRole('ROLE_ADMIN')...

    SpringSecurity学习总结源代码

    SpringSecurity是Java开发中用于构建安全Web应用的框架,它提供了强大的身份验证、...在学习过程中,分析提供的源代码和示例将有助于深入理解SpringSecurity的工作原理,并能帮助你在实际项目中有效地应用这些知识。

    spring security 学习总结文档

    【Spring Security 学习总结】 Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,用于保护基于 Java 的应用程序。本学习总结文档主要针对初学者,旨在剖析一个不安全的应用程序并阐述如何通过 ...

    Spring Security学习总结

    在"Spring Security学习总结一(补命名空间配置)"的文件中,可能涵盖了如何在Spring Security的XML配置中补充命名空间的步骤。命名空间的引入是为了简化配置,例如`&lt;http&gt;`元素用于配置安全拦截和访问规则,`...

    SpringSecurity学习总结一.pdf

    SpringSecurity学习总结一.pdf

    REST-spring-security.rar_java rest_java security_rest_rest secu

    总结来说,"REST-spring-security"项目展示了如何使用Spring Security来保护RESTful Web服务,包括身份验证、授权、访问控制和安全配置。这个项目可以帮助开发者理解如何在实际应用中实现安全的REST API,确保服务的...

    Spring_Security_学习总结

    ### Spring Security 学习总结 #### 一、Spring Security 概述 Spring Security 是一个功能强大的安全框架,它为基于 Java 的应用程序提供了认证(authentication)和授权(authorization)功能。在 Spring ...

    spring security 3.1学习资料 及 附件下载

    总结,Spring Security 3.1作为一款强大的安全框架,虽然版本较旧,但仍值得开发者深入研究。通过学习和实践,我们可以掌握如何构建安全的Web应用,并理解其背后的原理,为今后的安全开发打下坚实基础。

    精彩:Spring Security 演讲PPT

    ### Spring Security 概述与应用实践 #### 一、引言 在当今互联网时代,网络安全问题日益凸显,尤其是Web应用程序的...同时,结合实际案例的学习,能够帮助我们更好地理解和掌握Spring Security的核心概念与使用技巧。

    Spring_Security3_源码分析

    总结,Spring Security 3的源码分析是一个深度学习的过程,涵盖了安全领域的多个方面。通过理解其内部工作机制,开发者可以更好地利用这一强大的框架,为应用程序提供安全的保障。同时,源码分析也能帮助开发者解决...

    Spring_Security_官方文档

    对于初学者,建议从官方文档或教程开始学习,逐步熟悉Spring Security的安装、配置和使用流程。 #### Security命名空间配置 Spring Security通过XML命名空间简化了安全相关的配置。这部分文档详细介绍了如何使用...

    springsecurity:Spring安全学习总结

    spring security 学习总结暑假的时候在学习了Spring安全并成功运用到了项目中。在实践中摸索出了一套结合JSON +智威汤逊(JSON网络令牌)+Spring引导+ Spring Security的技术的权限方案趁着国庆假期记录一下。 内容 ...

    spring Security3中文教程,经典的

    ### Spring Security3中文教程知识点概览 #### 一、安全核心概念与起步 Spring Security是Spring框架中的一个重要组成部分,主要用于为Web应用提供安全防护。它不仅提供了强大的认证和授权功能,还支持各种加密...

    springSecurityTest.zip

    总结起来,"springSecurityTest.zip"文件提供了一个完整的环境,让你可以动手实践Spring Security的基础用法。通过学习其中的代码、笔记和文档,你将理解Spring Security如何与Spring框架协同工作,如何设置认证和...

Global site tag (gtag.js) - Google Analytics