4、Spring_Security_安全权限管理手册

来源:互联网 发布:图片批量下载软件 编辑:程序博客网 时间:2024/05/16 17:37
Spring Security 3.0 安全权限管理手册 参考文献:1、www.family168.com中的spring security权限管理手册。2、spring security3.0权限管理手册3、spring的相关资料。 本文档内容仅仅作为公司权限管理资料用,对于企业来说,权限管理将是系统中的非常重要的一个模块,权限的设计也是参考相关资料进行整理和补充。系统将通过数据库进行管理用户权限。 权限管理搭建要的问题:1、区分Authentication(验证)与Authorization(授权)验证这个用户是谁?用户身份可靠吗?授权某用户A是否可以访问资源R某用户A是否可以执行M操作某用户A是否可以对资源R执行M操作2、SS中的验证特点支持多种验证方式支持多种加密格式支持组件的扩展和替换可以本地化输出信息3、SS中的授权特点支持多种仲裁方式支持组件的扩展和替换支持对页面访问、方法访问、对象访问的授权。4、SS核心安全实现Web安全通过配置Servlet Filter激活SS中的过滤器链实现Session一致性验证实现免登陆验证(Remember-Me验证)提供一系列标签库进行页面元素的安全控制方法安全通过AOP模式实现安全代理Web安全与方法安全均可以使用表达式语言定义访问规则5、配置SS配置Web.xml,应用安全过滤器配置Spring,验证与授权部分在web页面中获取用户身份在web页面中应用安全标签库实现方法级安全6、配置web.xml7、Spring配置文件中设置命名空间8、通过数据库验证用户身份9、完善web页面验证规则10、自定义验证配置11、本地化消息输出(国际化)   根据公司项目的开发要求和集合spring security3.0功能,公司将通过数据库进行对用户身份验证和授权,系统将建立5个基础表进行对权利的管理。 第一部分 数据库设计1、表设计表1:用户表(pub_users)序号字段类型含义备注1User_IdVchar(32)用户idPK2user_accountVchar(30)登陆用户名(登陆号) 3User_nameVchar(40)用户姓名 4user_PasswordVchar(100)用户密码 5EnabledInt是否被禁用0禁用1正常6isSysInt是否是超级用户0非1是7user_DEScVchar(100)描述 说明:pub_users表中的登录名和密码用来控制用户的登录。表2:权限表(pub_authorities)序号字段类型含义备注1authority_IdVchar(32)权限idPK2Authority_nameVchar(40)权限名称 3Authority_DEScVchar(100)权限描述 4EnabledInt是否被禁用0禁用1正常5isSysInt是否是超级权限0非1是说明:pub_authorities表中描述的是系统拥有哪些权限,如果要详细分类,可以将一个url定义一个权限,那样就能对所有资源进行管理。表3:角色表(pub_roles)序号字段类型含义备注1role_IdVchar(32)角色idPK2role_nameVchar(100)角色名称 3role_DEScVchar(100)角色描述 4EnabledInt是否被禁用0禁用1正常5isSysInt是否是超级权限0非1是说明:pub_roles表中描述的是系统按用户分类或按照功能模块分类,将系统进行整合归类管理。表4:资源表(pub_resources)序号字段类型含义备注1resource_IdVchar(32)资源idPK2resource_nameVchar(100)资源名称 3resource _typeVchar(40)资源类型url、method4priorityint资源优先权即排序5resource _stringVchar(200)资源链接 6resource_DEScVchar(100)资源描述 7EnabledInt是否被禁用0禁用1正常8isSysInt是否是超级权限0非1是说明:pub_roles表中描述的是系统需要保护的资源及(url或方法)。以上四个表是权限管理的基础表(用户表、权限表、角色表、资源表)。 表5:用户角色连接表(pub_users_roles)序号字段类型含义备注1IdIndetityId主键PK2user_IdVchar(32)用户id 3role_idVchar(32)角色id 说明:用来管理用户和角色的关系。表6:角色权限连接表(pub_roles_authorities)序号字段类型含义备注1IdIndetityId主键PK2role _IdVchar(32)角色id 3authority_IdVchar(32)权限id 说明:用来管理角色和权限的关系。表7:权限资源连接表(pub_authorities_resources)序号字段类型含义备注1IdIndetityId主键PK2authority_IdVchar(32)权限id 3resource_IdVchar(32)资源id 说明:用来管理角色和权限的关系。2、建表语句如下(数据库采用MS SQL 2000):createtable pub_users(    user_id varchar(32),     user_account varchar(30),     user_name varchar(40),     user_password varchar(100),     user_desc varchar(100),     enabled int,     issysint);altertable pub_users add constraint pk_pub_users primary key(user_id); createtable pub_authorities(  authority_id varchar(32),     authority_name varchar(40),     authority_desc varchar(100),     enabledint,     issysint);altertable pub_authorities add constraint pk_pub_authorities primarykey(authority_id); createtable pub_roles(  role_id varchar(32),     role_name varchar(40),     role_desc varchar(100),     enabled int,     issysint);altertable pub_roles add constraint pk_pub_roles primary key(role_id); createtable pub_resources(  resource_id varchar(32),     resource_name varchar(100),     resource_desc varchar(100),     resource_type varchar(40),     resource_string varchar(200),     priority int,     enabled int,     issysint);altertable pub_resources add constraint pk_pub_resources primary key(resource_id); createtable pub_users_roles(     id numeric(12,0) IDENTITY NOT NULL,     user_id varchar(32),     role_id varchar(32),     enabled int);altertable pub_users_roles add constraint pk_pub_users_roles primary key(id);altertable pub_users_roles add constraint fk_users_roles_users foreign key(user_id)references pub_users(user_id);altertable pub_users_roles add constraint fk_users_roles_roles foreign key(role_id)references pub_roles(role_id);  createtable pub_roles_authorities(     id numeric(12,0) IDENTITY NOT NULL,     role_id varchar(32),     authority_id varchar(32),     enabled int);altertable pub_roles_authorities add constraint pk_pub_roles_authorities primarykey(id);altertable pub_roles_authorities add constraint fk_pub_roles_authorities_authoritiesforeign key(authority_id) references pub_authorities(authority_id);altertable pub_roles_authorities add constraint fk_pub_roles_authorities_rolesforeign key(role_id) references pub_roles(role_id); createtable pub_authorities_resources(     id numeric(12,0) IDENTITY NOT NULL,     authority_id varchar(32),     resource_id varchar(32),     enabled int);altertable pub_authorities_resources add constraint pk_pub_authorities_resourcesprimary key(id);altertable pub_authorities_resources add constraintfk_pub_authorities_resources_authorities foreign key(authority_id) referencespub_authorities(authority_id);altertable pub_authorities_resources add constraintfk_pub_authorities_resources_resources foreign key(resource_id) referencespub_resources(resource_id); 3、E-R图如下: 第二部分 WEB数据库整合提示:相关代码请参考项目模块1、将数据库表结构和Hibernate建立映射,本系统采用annotation进行对数据库进行零配置处理(请参考hibernate映射),如图。2、建立权限的Dao层。3、建立权限的Service层  4、配置web.xml   <?xml version="1.0" encoding="UTF-8"?><web-app version="2.5"xmlns="http://java.sun.com/xml/ns/javaee"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">     <display-name>rstframe</display-name>     <context-param>       <param-name>webAppRootKey</param-name>       <param-value>rstframe.root</param-value>    </context-param>       <context-param>       <param-name>log4jConfigLocation</param-name>       <param-value>classpath:log4j.properties</param-value>    </context-param>       <context-param>       <param-name>log4jRefreshInterval</param-name>       <param-value>60000</param-value>    </context-param>     <!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔       此参数用于后面的Spring Context Loader -->    <context-param>       <param-name>contextConfigLocation</param-name>       <param-value>           classpath*:/applicationContext.xml,           classpath*:/applicationContext-rstframe.xml       </param-value>    </context-param>     <!-- Character Encoding filter -->    <filter>       <filter-name>encodingFilter</filter-name>       <filter-class>           org.springframework.web.filter.CharacterEncodingFilter       </filter-class>       <init-param>           <param-name>encoding</param-name>           <param-value>UTF-8</param-value>       </init-param>    </filter>    <filter-mapping>       <filter-name>encodingFilter</filter-name>       <url-pattern>/*</url-pattern>    </filter-mapping>     <!-- SpringSide's Hibernate OpenSession In View filter-->    <filter>       <filter-name>hibernateOpenSessionInViewFilter</filter-name>       <filter-class>           com.rstco.frame.modules.orm.hibernate.OpenSessionInViewFilter       </filter-class>       <init-param>           <param-name>excludeSuffixs</param-name>           <param-value>js,css,jpg,gif</param-value>       </init-param>    </filter>       <filter-mapping>       <filter-name>hibernateOpenSessionInViewFilter</filter-name>       <url-pattern>/*</url-pattern>    </filter-mapping>     <!-- SpringSecurity filter-->    <filter>        <filter-name>springSecurityFilterChain</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>    </filter>    <filter-mapping>        <filter-name>springSecurityFilterChain</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>     <!-- Struts2 filter, actionPackages -->    <filter>       <filter-name>struts2Filter</filter-name>       <filter-class>           org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter       </filter-class>    </filter>    <filter-mapping>       <filter-name>struts2Filter</filter-name>       <url-pattern>/*</url-pattern>    </filter-mapping>    <!--Spring的ApplicationContext 载入 -->    <listener>       <listener-class>           org.springframework.web.context.ContextLoaderListener       </listener-class>    </listener>    <listener>       <listener-class>           org.springframework.web.util.Log4jConfigListener       </listener-class>    </listener>      <!-- Spring 刷新Introspector防止内存泄露 -->    <listener>       <listener-class>           org.springframework.web.util.IntrospectorCleanupListener       </listener-class>    </listener>    <!-- 防止多人登陆 ,控制一个用户只能登录一次,不能在其他地方重新登录-->    <listener>       <listener-class>           org.springframework.security.web.session.HttpSessionEventPublisher       </listener-class>    </listener>     <!-- session超时定义,单位为分钟 -->    <session-config>       <session-timeout>20</session-timeout>    </session-config>     <welcome-file-list>       <welcome-file>index.jsp</welcome-file>    </welcome-file-list>     <!-- error page -->    <error-page>       <exception-type>java.lang.Throwable</exception-type>       <location>/common/500.jsp</location>    </error-page>    <error-page>       <error-code>500</error-code>       <location>/common/500.jsp</location>    </error-page>    <error-page>       <error-code>404</error-code>       <location>/common/404.jsp</location>    </error-page>    <error-page>       <error-code>403</error-code>       <location>/common/403.jsp</location>    </error-page>     <jsp-config>       <taglib>           <taglib-uri>/WEB-INF/struts-menu-el.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/struts-menu-el.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/struts-menu.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/struts-menu.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/c.tld</taglib-uri>           <taglib-location>/WEB-INF/tlds/c.tld</taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/fmt.tld</taglib-uri>           <taglib-location>/WEB-INF/tlds/fmt.tld</taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/fn.tld</taglib-uri>           <taglib-location>/WEB-INF/tlds/fn.tld</taglib-location>       </taglib>       <!--loushang tld-->       <taglib>           <taglib-uri>/WEB-INF/web-date.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-date.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-flex.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-flex.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-graph.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-graph.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-grid.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-grid.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-html.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-html.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-list.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-list.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-loushang.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-loushang.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-menu.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-menu.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-multitab.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-multitab.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-seltree.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-seltree.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-tab.tld</taglib-uri>           <taglib-location>/WEB-INF/tlds/web-tab.tld</taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-tree.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-tree.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-widgets.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-widgets.tld           </taglib-location>       </taglib>       <taglib>           <taglib-uri>/WEB-INF/web-i18n.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/web-i18n.tld           </taglib-location>       </taglib>       <!-- loushang end -->       <taglib>           <taglib-uri>/WEB-INF/gystudio.tld</taglib-uri>           <taglib-location>              /WEB-INF/tlds/gystudio.tld           </taglib-location>       </taglib>    </jsp-config>       <mime-mapping>       <extension>rar</extension>       <mime-type>application/rar</mime-type>    </mime-mapping> </web-app>5、配置spring security3.0中的xml文件   文件名:applicationContext-security.xml<?xml version="1.0"encoding="UTF-8"?><beans:beans xmlns="http://www.springframework.org/schema/security"    xmlns:beans="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd          http://www.springframework.org/schema/security          http://www.springframework.org/schema/security/spring-security-3.0.xsd">       <beans:description>SpringSecurity安全配置</beans:description>       <!-- http安全配置 -->     <http auto-config="true">       <intercept-url pattern="/css/**"filters="none" />       <intercept-url pattern="/images/**"filters="none" />       <intercept-url pattern="/js/**"filters="none" />       <intercept-url pattern="/login.jsp"filters="none" />       <!--       <intercept-url pattern="/index.jsp"  access="ROLE_USER"/>       <intercept-url pattern="/main.jsp"  access="ROLE_ADAMIN"/>        -->       <form-login login-page="/login.jsp"default-target-url="/index.jsp"            authentication-failure-url="/login.jsp?error=1"/>       <!-- 尝试访问没有权限的页面时跳转的页面 -->         <access-denied-handler error-page="/common/403.jsp"/>             <logout logout-success-url="/login.jsp"/>                <session-management>        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>         </session-management>        <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,       这个filter位于FILTER_SECURITY_INTERCEPTOR之前 -->         <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>           </http>     <!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,    我们的所有控制将在这三个类中实现,解释详见具体配置  -->    <beans:bean id="myFilter"class="com.rstco.frame.pub.security.interceptor.MyFilterSecurityInterceptor">        <beans:property name="authenticationManager"           ref="authenticationManager" />        <beans:property name="accessDecisionManager"           ref="myAccessDecisionManagerBean" />        <beans:property name="securityMetadataSource"           ref="mySecurityMetadataSource" />    </beans:bean>      <!-- 验证配置,认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->    <authentication-manager alias="authenticationManager">                <authentication-provider user-service-ref="userDetailsService">          <!--           <s:password-encoder hash="sha" />            -->       </authentication-provider>            </authentication-manager>       <!-- 项目实现的用户查询服务,将用户信息查询出来  -->    <beans:bean id="userDetailsService" class="com.rstco.frame.pub.security.support.MyUserDetailService"/>     <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源     -->    <beans:bean id="myAccessDecisionManagerBean"       class="com.rstco.frame.pub.security.support.MyAccessDecisionManager">    </beans:bean>     <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问-->    <beans:bean id="mySecurityMetadataSource"       class="com.rstco.frame.pub.security.support.MyInvocationSecurityMetadataSourceService">    </beans:bean>              <!-- 定义国际化 -->    <beans:bean id="messageSource"         class="org.springframework.context.support.ReloadableResourceBundleMessageSource">        <beans:property name="basename"           value="classpath:org/springframework/security/messages_zh_CN"/>    </beans:bean></beans:beans>  第三部分 SS3.0的实现这是项目的主体部分:这四个类说明如下。一、用来获得用户验证信息(MyUserDetailService)代码如下:package com.rstco.frame.pub.security.support; import java.util.ArrayList;import java.util.Collection;import java.util.List; importorg.springframework.beans.factory.annotation.Autowired;import org.springframework.dao.DataAccessException;import org.springframework.security.core.GrantedAuthority;importorg.springframework.security.core.userdetails.User;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Service; importcom.rstco.frame.pub.security.dao.PubAuthoritiesResourcesDao;import com.rstco.frame.pub.security.dao.PubUsersDao;import com.rstco.frame.pub.security.entity.PubAuthorities;importcom.rstco.frame.pub.security.entity.PubAuthoritiesResources; //你就可以从数据库中读入用户的密码,角色信息,是否锁定,账号是否过期@Servicepublic class MyUserDetailService implementsUserDetailsService  {   @Autowired   privatePubUsersDao pubUsersDao;   @Autowired   privatePubAuthoritiesResourcesDao pubAuthoritiesResourcesDao;         publicUserDetails loadUserByUsername(String username)          throwsUsernameNotFoundException, DataAccessException {                   Collection<GrantedAuthority>auths=new ArrayList<GrantedAuthority>();          //取得用户的权限          List<PubAuthorities>auth=pubUsersDao.findAuthByUserName(username);          Stringpassword=null;          //取得用户的密码          password=pubUsersDao.findUserByname(username).get(0).getUserPassword();                   List<PubAuthoritiesResources>aaa=pubAuthoritiesResourcesDao.getAll();                    User user = new User(username,                password,true, true, true, true, auths);                     return user;   } }二、最核心的地方,就是提供某个资源对应的权限定义,取得所有角色(auth)的对应资源数据(MyInvocationSecurityMetadataSourceService)代码如下:package com.rstco.frame.pub.security.support; import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map; import javax.servlet.ServletContext; import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;import org.springframework.security.web.util.AntUrlPathMatcher;import org.springframework.security.web.util.UrlMatcher;import org.springframework.stereotype.Service; import com.rstco.frame.modules.orm.hibernate.HibernateDao;importcom.rstco.frame.pub.security.dao.PubAuthoritiesResourcesDao;import com.rstco.frame.pub.security.entity.PubAuthorities;import com.rstco.frame.pub.security.entity.PubResources; /* * * 最核心的地方,就是提供某个资源对应的权限定义,即getAttributes方法返回的结果。 * 注意,我例子中使用的是AntUrlPathMatcher这个path matcher来检查URL是否与资源定义匹配, * 事实上你还要用正则的方式来匹配,或者自己实现一个matcher。 * * 此类在初始化时,应该取到所有资源及其对应角色的定义 * * 说明:对于方法的spring注入,只能在方法和成员变量里注入, * 如果一个类要进行实例化的时候,不能注入对象和操作对象, * 所以在构造函数里不能进行操作注入的数据。 */@Servicepublic class MyInvocationSecurityMetadataSourceService  implements      FilterInvocationSecurityMetadataSource{      @Autowired   privatePubAuthoritiesResourcesDao pubAuthoritiesResourcesDao;    private UrlMatcherurlMatcher = new AntUrlPathMatcher();   private staticMap<String, Collection<ConfigAttribute>> resourceMap = null;    publicMyInvocationSecurityMetadataSourceService() {      loadResourceDefine();   } /*    private void loadResourceDefine() {           resourceMap = new HashMap<String,Collection<ConfigAttribute>>();           Collection<ConfigAttribute> atts= new ArrayList<ConfigAttribute>();           ConfigAttribute ca = newSecurityConfig("ROLE_ADMIN");           atts.add(ca);           resourceMap.put("/index.jsp",atts);           resourceMap.put("/i.jsp",atts);       }*/     private voidloadResourceDefine() {      ApplicationContextcontext = newClassPathXmlApplicationContext("applicationContext.xml");      SessionFactorysessionFactory = (SessionFactory)context.getBean("sessionFactory");           Session session =sessionFactory.openSession();      List<String>query=session.createSQLQuery("select authority_name from pub_authorities").list();                resourceMap = newHashMap<String, Collection<ConfigAttribute>>();      Collection<ConfigAttribute>atts = new ArrayList<ConfigAttribute>();       //List<PubAuthorities>auths =session.createQuery(arg0); //pubAuthoritiesResourcesDao.findAuthAll();             for (String auth :query) {          ConfigAttributeca = new SecurityConfig(auth);// "ROLE_ADMIN"          // atts.add(ca);                   List<String>query1=session.createSQLQuery("select resource_string " +                 "fromPub_Authorities_Resources,Pub_Resources, Pub_authorities " +                 "wherePub_Authorities_Resources.resource_id=Pub_Resources.resource_id and " +                 "Pub_Authorities_Resources.resource_id=Pub_authorities.authority_id  and " +                 "  Authority_name='"+auth+"'").list();                   for (String res :query1) {             String url =res;             // 判断资源文件和权限的对应关系,如果已经存在,要进行增加             if(resourceMap.containsKey(url)) {                 Collection<ConfigAttribute>value = resourceMap.get(url);                 value.add(ca);                 resourceMap.put(url,value);                 //"log.jsp","role_user,role_admin"             } else {                 atts.add(ca);                 resourceMap.put(url,atts);             }              resourceMap.put(url, atts);          }      }   }    // According to a URL,Find out permission configuration of this URL.   publicCollection<ConfigAttribute> getAttributes(Object object)          throwsIllegalArgumentException {      // guess object is aURL.      String url =((FilterInvocation) object).getRequestUrl();      Iterator<String>ite = resourceMap.keySet().iterator();      while (ite.hasNext()){          String resURL =ite.next();          if(urlMatcher.pathMatchesUrl(url, resURL)) {             returnresourceMap.get(resURL);          }      }      return null;   }    public booleansupports(Class<?> clazz) {      return true;   }    publicCollection<ConfigAttribute> getAllConfigAttributes() {      return null;   } }三、最重要的是decide方法,如果不存在对该资源的定义,直接放行;否则,如果找到正确的角色,即认为拥有权限,并放行,否则throw new AccessDeniedException("no right");这样,就会进入上面提到的403.jsp页面。(MyAccessDecisionManager)代码如下: package com.rstco.frame.pub.security.support; import java.util.Collection;import java.util.Iterator; importorg.springframework.security.access.AccessDecisionManager;importorg.springframework.security.access.AccessDeniedException;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;importorg.springframework.security.authentication.InsufficientAuthenticationException;import org.springframework.security.core.Authentication;import org.springframework.security.core.GrantedAuthority;  public class MyAccessDecisionManager implementsAccessDecisionManager {     //In this method, needto compare authentication with configAttributes.    // 1, A object is aURL, a filter was find permission configuration by this URL, and pass to here.    // 2, Checkauthentication has attribute in permission configuration (configAttributes)    // 3, If not matchcorresponding authentication, throw a AccessDeniedException.    public voiddecide(Authentication authentication, Object object,           Collection<ConfigAttribute> configAttributes)            throwsAccessDeniedException, InsufficientAuthenticationException {       if(configAttributes == null){            return ;        }       System.out.println(object.toString()); //object is a URL.        Iterator<ConfigAttribute>ite=configAttributes.iterator();       while(ite.hasNext()){           ConfigAttribute ca=ite.next();            StringneedRole=((SecurityConfig)ca).getAttribute();           for(GrantedAuthority ga:authentication.getAuthorities()){               if(needRole.equals(ga.getAuthority())){ //ga is user's role.                   return;                }            }        }        throw newAccessDeniedException("no right");    }     public booleansupports(ConfigAttribute attribute) {        // TODOAuto-generated method stub        return true;    }     public booleansupports(Class<?> clazz) {        return true;    }  }四、这个过滤器要插入到授权之前。最核心的代码就是invoke方法中的InterceptorStatusToken token = super.beforeInvocation(fi);这一句,即在执行doFilter之前,进行权限的检查,而具体的实现已经交给accessDecisionManager了(MyFilterSecurityInterceptor)代码如下:packagecom.rstco.frame.pub.security.interceptor; import java.io.IOException; import javax.servlet.Filter;import javax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse; importorg.springframework.beans.factory.annotation.Autowired;import org.springframework.security.access.AccessDecisionManager;importorg.springframework.security.access.SecurityMetadataSource;importorg.springframework.security.access.intercept.AbstractSecurityInterceptor;importorg.springframework.security.access.intercept.InterceptorStatusToken;importorg.springframework.security.web.FilterInvocation;importorg.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public classMyFilterSecurityInterceptor extends AbstractSecurityInterceptor       implements Filter {     private FilterInvocationSecurityMetadataSourcesecurityMetadataSource;         public void doFilter(ServletRequest request, ServletResponseresponse,           FilterChain chain) throws IOException, ServletException {       FilterInvocation fi = new FilterInvocation(request, response,chain);       invoke(fi);    }     public FilterInvocationSecurityMetadataSourcegetSecurityMetadataSource() {       return this.securityMetadataSource;    }     public Class<? extends Object> getSecureObjectClass() {       return FilterInvocation.class;    }     public void invoke(FilterInvocation fi) throws IOException,           ServletException {       InterceptorStatusToken token = super.beforeInvocation(fi);       try {           fi.getChain().doFilter(fi.getRequest(), fi.getResponse());       } finally {           super.afterInvocation(token, null);       }    }       @Override    public SecurityMetadataSource obtainSecurityMetadataSource() {       return this.securityMetadataSource;    }     public void setSecurityMetadataSource(           FilterInvocationSecurityMetadataSource securityMetadataSource){       System.out.println("abc=======================edf");       this.securityMetadataSource = securityMetadataSource;    }     public void destroy() {       // TODO Auto-generated method stub          }     public void init(FilterConfig filterconfig) throwsServletException {       // TODO Auto-generated method stub          }      }    如有异议,请加qq:89168934,互相学习交流。                                               


0 0
原创粉丝点击