`
m635674608
  • 浏览: 5028773 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Spring Security二

 
阅读更多

           SpringSide(你可以去官网了解更多信息,我也是从这里开始了解和学习Spring Security的)

前一篇文章里介绍了Spring Security的一些基础知识,相信你对Spring Security的工作流程已经有了一定的了解,如果你同时在读源代码,那你应该可以认识的更深刻。在这篇文章里,我们将对Spring Security进行一些自定义的扩展,比如自定义实现UserDetailsService,保护业务方法以及如何对用户权限等信息进行动态的配置管理。

说明:
如果你通过Google搜索,可以找到很 多类似主题的文章,本文的目的在于通过这些实例来介绍的工作
原理,我觉得这些才是最重要的。相信你在读完本文之后应该可以按照自己的想法去扩展Spring Secu
rity,这也是我写这两篇文章的目的。希望能对 初学者们有所帮助。
 

废话少说,咱们直接进入正题。

一 自定义UserDetailsService实现

UserDetailsService接口,这个接口中只定义了唯一的UserDetails loadUserByUsername(String username)方法,它通过用户名来获取整个UserDetails对象。

前一篇文章已经介绍了系统提供的默认实现方式InMemoryDaoImpl,它从配置文件中读取用户的身份信息(用户名,密码等),如果你的客户想修改用户信息,就需要直接修改配置文件(你需要告诉用户配置文件的路径,应该在什么地方修改,如何把明文密码通过MD5加密以及如何重启服务器等)。听起来是不是很费劲啊!

在实际应用中,我们可能需要提供动态的方式来获取用户身份信息,最常用的莫过于数据库了,当然也可以是LDAP服务器等。本文首先介绍系统提供的一个默认实现类JdbcDaoImplorg.springframework.security.userdetails.jdbc. JdbcDaoImpl),它通过用户名从数据库中获取用户身份信息,修改配置文件,将userDetailsService Bean的配置修改如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->1 <bean id="userDetailsService"
2 class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl"
3 p:dataSource-ref="dataSource"
4 p:usersByUsernameQuery="select userName, passWord, enabled, from users where userName=?"
5 p:authoritiesByUsernameQuery="select 
6 u.userName,r.roleName from users u,roles 
7 r,users_roles ur where u.userId=ur.userId and 
8 r.roleId=ur.roleId and u.userName=?"/>

JdbcDaoImpl类继承自Spring Framework的JdbcDaoSupport类并实现了UserDetailsService接口,因为从数据库中读取信息,所以首先需要一个数据源对象,这里不在多说,这里需要重点介绍的是usersByUsernameQueryauthoritiesByUsernameQuery,属性,它们的值都是一条SQL语句,JdbcDaoImpl类通过SQL从数据库中检索相应的信息,usersByUsernameQuery属性定义了通过用户名检索用户信息的SQL语句,包括用户名,密码以及用户是否可用,authoritiesByUsernameQuery属性定义了通过用户名检索用户权限信息的SQL语句,这两个属性都引用一个MappingSqlQuery(请参考Spring Framework相关资料)例,MappingSqlQuerymapRow()方法将一个ResultSet(结果集)中的字段映射一个,Spring Security为我们提供了默认的数据库表,如下图所示(摘自《Spring in Action》)

 

<!--[if supportFields]-->1<!--[if supportFields]--> JdbcDaoImp数据库表

如果我们需要获取用户的其它信息就需要自己来扩展系统的默认实现,首先应该了解一下UserDetailsService实现的原理,还是要回到源代码,以下是JdbcDaoImpl类的部分代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1 private class UsersByUsernameMapping extends MappingSqlQuery {
 2 
 3      protected UsersByUsernameMapping(DataSource ds) {
 4 
 5             super(ds, usersByUsernameQuery);
 6 
 7             declareParameter(new SqlParameter(Types.VARCHAR));
 8 
 9             compile();
10 
11      }
12 
13      protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
14 
15             String username = rs.getString(1);
16 
17             String password = rs.getString(2);
18 
19             boolean enabled = rs.getBoolean(3);
20 
21             UserDetails user = new User(username, password, enabled, true,
22 
23                truetruenew GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});
24 
25             return user;
26      }
27 
28 }

也许你已经看出什么来了,对了,系统返回的UserDetails对象就是从这里来的,这就是读源代码的好处,DaoAuthenticationProvider提供者通过调用自己的authenticate(Authentication authentication)方法将用户在登录页面输入的用户信息与这里从数据库获取的用户信息进行匹配,如果匹配成功则将用户的权限信息赋给Authentication对象并将其存放在SecurityContext中,供其它请求使用。

那么我们要扩展获得更多的用户信息,就要从这里下手了(数据库表这里不在列出来,可以参考项目的WebRoot/db目录下的schema.sql文件)。比如我们自己的数据库设计中是通过一个loginId和用户名来登录或者我们需要额外ID,EMAIL地址等信息,MySecurityJdbcDaoImpl实现如下:

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1 protectedclass UsersByUsernameMapping extends MappingSqlQuery {
 2 
 3        protected UsersByUsernameMapping(DataSource ds) {
 4 
 5            super(ds, usersByUsernameQuery);
 6 
 7            declareParameter(new SqlParameter(Types.VARCHAR));
 8 
 9            compile();
10 
11        }
12 
13        protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
14 
15            // TODO Auto-generated method stub
16 
17            String userName = rs.getString(1);
18 
19            String passWord = rs.getString(2);
20 
21            boolean enabled = rs.getBoolean(3);
22 
23            Integer userId = rs.getInt(4);
24 
25            String email = rs.getString(5);
26 
27        MyUserDetails user = new MyUser(userName, passWord, enabled, true
28                                                true,truenew GrantedAuthority[]{new 
29                                                GrantedAuthorityImpl("HOLDER")});
30 
31            user.setEmail(email);
32 
33            user.setUserId(userId);
34 
35            return user;
36 
37        }
38 
39 }

如果你已经看过源代码,你会发现这里只是其中的一部分代码 ,具体的实现请看项目的MySecurityJdbcDaoImpl类实现,以及MyUserDetailsMyUser类,这里步在一一列出。

如果使用Hibernate来操作数据库,你也可以从你的DAO中获取用户信息,最后你只要将存放了用户身份信息和权限信息的列表(List)返回给系统就可以。

提示:
这里没有介绍更多的细节问题,主要还是想你自己能通过读源代码来加深理解,本人水平也有限,
相信你从源代码中能悟出更多的有价值的东西。
 

    每当用户请求一个受保护的资源时,就会调用认证管理器以获取用户认证信息,但是如果我们的用户信息保存在数据库中,那么每次请求都从数据库中获取信息将会影响系统性能,那么将用户信息进行缓存就有必要了,下面就介绍如何在Spring Security中使用缓存。

缓存用户信息

查看AuthenticationProvider接口的实现类AbstractUserDetailsAuthenticationProvider抽象类(我们配置文件中配置的DaoAuthenticationProvider类继承了该类)的源代码,会有一行代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->1 UserDetails user = this.userCache.getUserFromCache(username);

DaoAuthenticationProvider认证提供者使用UserCache接口的实现来实现对用户信息的缓存,修改DaoAuthenticationProvider的配置如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->1 <bean id="daoAuthenticationProvider"
2 class="org.springframework.security.providers.dao.DaoAuthenticationProvider"
3     p:userCache-ref="userCache"
4     p:passwordEncoder-ref="passwordEncoder"
5     p:userDetailsService- ref="userDetailsService"/>

这里我们加入了对userCache Bean的引用,userCache使用Ehcache来实现对用户信息的缓存。userCache配置如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1 <bean id="userCache"
 2 class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache"
 3     p:cache-ref="cache"/>
 4 <bean id="cache"
 5 class="org.springframework.cache.ehcache.EhCacheFactoryBean"
 6     p:cacheManager-ref="cacheManager"
 7     p:cacheName="userCache"/>
 8 <bean id="cacheManager"
 9 class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
10     p:configLocation="classpath:ehcache.xml">
11 </bean>

    我们这里使用的是EhCacheBasedUserCache,也就是用EhCache实现缓存的,另外系统还提供了一个默认的实现类NullUserCache类,我们可以通过源代码了解到,无论上面使用这个类都返回一个null值,也就是不使用缓存。

保护业务方法

从第一篇文章中我们已经了解到,Spring Security使用Servlet过滤器来拦截用户的请求来保护WEB资源,而这里却是使用Spring 框架的AOP来提供对方法的声明式保护。它通过一个拦截器来拦截方法调用,并调用方法安全拦截器来保护方法。

在介绍之前,我们先回忆一下过滤器安全拦截器是如何工作的。过滤器安全拦截器首先调用AuthenticationManager认证管理器认证用户信息,如果用过认证则调用AccessDecisionManager访问决策管理器来验证用户是否有权限访问objectDefinitionSource中配置的受保护资源。

首先看看如何配置方法安全拦截器,它和过滤器安全拦截器一方继承自AbstractSecurityInterceptor抽象类(请看源代码),如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->1 <bean id="methodSecurityInterceptor"
2 class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor"
3     p:authenticationManager-ref="authenticationManager"
4     p:accessDecisionManager-ref="accessDecisionManager">
5     <property name="objectDefinitionSource">
6        <value>   
              com.test.service.UserService.get*=ROLE_SUPERVISOR
7        </value>
8     </property>
9 </bean>

这段代码是不是很眼熟啊,哈哈~,这和我们配置的过滤器安全拦截器几乎完全一样,方法安全拦截器的处理过程实际和过滤器安全拦截器的实现机制是相同的,这里就在累述,详细介绍请参考< Spring Security 学习总结一>中相关部分。但是也有不同的地方,那就是这里的objectDefinitionSource的配置,在等号前面的不在是URL资源,而是需要保护的业务方法,等号后面还是访问该方法需要的用户权限。我们这里配置的com.test.service.UserService.get*表示对com.test.service包下UserService类的所有以get开头的方法都需要ROLE_SUPERVISOR权限才能调用。这里使用了提供的实现方法MethodSecurityInterceptor,系统还给我们提供了aspectj的实现方式,这里不在介绍(我也正在学),读者可以参考其它相关资料。

之前已经提到过了,Spring Security使用Spring 框架的AOP来提供对方法的声明式保护,即拦截方法调用,那么接下来就是创建一个拦截器,配置如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 1 <bean id="autoProxyCreator"
 2 class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
 3     <property name="interceptorNames">
 4        <list>
 5        <value>methodSecurityInterceptor</value>
 6        </list>
 7     </property>
 8     <property name="beanNames">
 9        <list>
10            <value>userService</value>
11        </list>
12     </property>
13 </bean>

userService是我们在applicationContext.xml中配置的一个Bean,AOP的知识不是本文介绍的内容。到这里保护业务方法的配置就介绍完了。

将资源放在数据库中

现在,你的用户提出了新的需求,它们需要自己可以给系统用户分配或者取消权限。其实这个并不是什么新鲜事,作为开发者,你也应该为用户提供这样的功能。那么我们就需要这些受保护的资源和用户权限等信息都是动态的,你可以选择把它们存放在数据库中或者LDAP服务器上,本文以数据库为例,介绍如何实现用户权限的动态控制。

通过前面的介绍,你可能也注意到了,不管是MethodSecurityInterceptor还是FilterSecurityInterceptor都使用authenticationManageraccessDecisionManager属性用于验证用户,并且都是通过使用objectDefinitionSource属性来定义受保护的资源。不同的是过滤器安全拦截器将URL资源与权限关联,而方法安全拦截器将业务方法与权限关联。

你猜对了,我们要做的就是自定义这个objectDefinitionSource的实现,首先让我们来认识一下系统为我们提供的ObjectDefinitionSource接口,objectDefinitionSource属性正是指向此接口的实现类。该接口中定义了3个方法,ConfigAttributeDefinition getAttributes(Object object)方法用户获取保护资源对应的权限信息,该方法返回一个ConfigAttributeDefinition对象(位于org.springframework.security包下),通过源代码我们可以知道,该对象中实际就只有一个List列表,我们可以通过使用ConfigAttributeDefinition类的构造函数来创建这个List列表,这样,安全拦截器就通过调用getAttributes(Object object)方法来获取ConfigAttributeDefinition对象,并将该对象和当前用户拥有的Authentication对象传递给accessDecisionManager(访问决策管理器,请查看org.springframework.security.vote包下的AffirmativeBased类,该类是访问决策管理器的一个实现类,它通过一组投票者来决定用户是否有访问当前请求资源的权限),访问决策管理器在将其传递给AffirmativeBased类维护的投票者,这些投票者从ConfigAttributeDefinition对象中获取这个存放了访问保护资源需要的权限信息的列表,然后遍历这个列表并与Authentication对象中GrantedAuthority[]数据中的用户权限信息进行匹配,如果匹配成功,投票者就会投赞成票,否则就投反对票,最后访问决策管理器来统计这些投票决定用户是否能访问该资源。是不是又觉得乱了,还是那句话,如果你结合源代码你现在一定更明白了。

说了这么些,那我们到底应该如何来实现这个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接口。代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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方法:

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  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类的构造函数来初始化该对象。详细的实现还是请你看源代码。现在我们在配置文件添加自己的实现,如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->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):

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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文件中的配置,请查看该配置文件。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->1 <bean id="methodDefinitionSource"
2     class="org.security.intercept.method.DataBaseMethodInvocationDefinitionSource"
3     p:securityCacheManager-ref="securityCacheManager"/>

securityCacheManager属性定义了指向另一个Bean的引用,我们使用它从缓存中获取相应的信息。这个Bean和前一节中介绍的一样。只是这里我们获取的是方法保护定义资源。

    本文到此也结束了,还请各位多指教。

 来自http://www.blogjava.net/redhatlinux/archive/2008/09/01/226010.html

分享到:
评论

相关推荐

    spring security2配置

    1. **配置初始化**:在Spring Security 2中,我们需要创建一个配置类,继承自`org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter`。在这个类中,我们可以通过覆盖`...

    Spring Security 2 配置精讲

    Spring Security 2 配置精讲

    spring security 2 配置说明

    标题与描述均提到了“Spring Security 2 配置说明”,这表明文章旨在阐述Spring Security 2版本的配置细节,尤其是对于那些希望深入了解并正确应用该框架的安全特性开发者们。以下将基于给定的部分内容,深入解析...

    Spring Security 2 中文参考文档(chm)

    **Spring Security 2 中文参考文档** Spring Security是一款强大的安全框架,主要用于Java应用程序的安全管理。在Spring Security 2版本中,它提供了丰富的功能,包括身份验证、授权、访问控制以及安全相关的会话...

    Spring Security 2 参考手册 中文版 (html格式)

    `ca.html`和`springsecurity.html`的详细内容没有明确的描述,但根据常规,它们可能涉及证书权威(CA)和Spring Security的其他核心概念,比如自定义安全逻辑或者框架的高级特性。 总的来说,Spring Security 2 的...

    spring security2 例子

    在这个"spring security2 例子"中,我们可能会探索如何利用Spring Security 2版本来保护我们的应用程序。Spring Security 2虽然已经较为老旧(最新的版本是5.x),但它仍能帮助我们理解基本的安全概念和架构。 首先...

    Spring Security2中设置Cookie的保存时间

    在Spring Security 2中,配置Cookie的保存时间是一项重要的任务,因为这关乎到用户的会话持久性和安全性。Cookie是Web应用程序中用于存储用户状态的一种机制,例如登录信息、个性化设置等。正确设置Cookie的生命周期...

    精彩:Spring Security 演讲PPT

    随着Spring Security 2.x的发布,它提供了一种更为简洁且高效的方式来进行Web应用的安全管理。快速启动Spring Security 2.x,主要分为三个步骤: 1. **添加过滤器**: 在`web.xml`中加入`DelegatingFilterProxy`,...

    SpringSecurity2中文文档与开发实例

    这里包括Spring Security2的中文文档和一个基于Dao的开发实例,相信不管是对原来基于Acegi安全框架的开发人员还是现在基于Spring安全框架(Spring Security2实际上是Acegi2)的开发人员都有参考价值.

    Spring Security in Action

    Spring Security 实践指南 Spring Security 是一个基于 Java 的安全框架,旨在提供身份验证、授权和访问控制等功能。下面是 Spring Security 的主要知识点: 一、身份验证(Authentication) 身份验证是指对用户...

    spring security2.x配置

    详细的spring security2.x配置

    Spring Security 资料合集

    - Spring Security 可以与OAuth2框架集成,提供第三方服务的认证和授权,支持资源服务器、认证服务器和客户端的角色。 8. **Spring Security ACL**: - 对象级权限管理(ACL)允许开发者对应用内的具体对象实施细...

    SpringSecurity.pdf

    Spring Security是一个功能强大、高度定制的安全框架,它专门用于为基于Spring的应用程序提供安全性解决方案。Spring Security架构的设计初衷是为了解决认证和授权的需求,确保应用程序的安全性。它提供了全面的安全...

    springsecurity学习笔记

    在"springsecurity学习笔记"中,你可能会涉及以下主题: - Spring Security的基本配置,包括web安全配置和全局安全配置。 - 如何自定义认证和授权流程,比如实现自定义的AuthenticationProvider和...

    Spring Security 2 中文 CHM版

    自己在网络上看到并整理成CHM版本的。 原地址:http://www.family168.com/tutorial/springsecurity/html/springsecurity.html

    Spring Cloud Gateway 整合 Spring Security 统一登录认证鉴权

    2. **配置Spring Security**:我们需要在Spring Cloud Gateway项目中引入Spring Security依赖,并配置相关的安全配置类。这包括定义认证和授权的规则,例如基于JWT(JSON Web Tokens)的认证,或者基于OAuth2的授权...

    spring security 完整项目实例

    Spring Security支持基于表单的身份验证,也支持OAuth2和其他现代认证协议。 免登录功能,即Remember-Me服务,允许用户在一段时间内无须反复登录。这通过RememberMeServices接口实现,通常使用Token-Based策略,将...

    spring-security所需要的jar包,

    Acegi Security提供了一套基于Spring的认证和授权机制,但在Spring Security 2.x版本之后,大部分功能已被Spring Security自身所取代。 3. **spring-security-core-tiger-2.0.5.RELEASE-tests.jar**:这是一个测试...

Global site tag (gtag.js) - Google Analytics