﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-有点抽象-文章分类-Acegi</title><link>http://www.blogjava.net/bracling/category/48489.html</link><description>从现实中抽象出生活的实质，将原本的梦想逐渐变为现实！</description><language>zh-cn</language><lastBuildDate>Tue, 07 Jun 2011 21:06:00 GMT</lastBuildDate><pubDate>Tue, 07 Jun 2011 21:06:00 GMT</pubDate><ttl>60</ttl><item><title>Acegi + Spring + Hibernate + Struts 2搭建基于角色的权限控制系统</title><link>http://www.blogjava.net/bracling/articles/351887.html</link><dc:creator>有点抽象</dc:creator><author>有点抽象</author><pubDate>Tue, 07 Jun 2011 15:17:00 GMT</pubDate><guid>http://www.blogjava.net/bracling/articles/351887.html</guid><wfw:comment>http://www.blogjava.net/bracling/comments/351887.html</wfw:comment><comments>http://www.blogjava.net/bracling/articles/351887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bracling/comments/commentRss/351887.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bracling/services/trackbacks/351887.html</trackback:ping><description><![CDATA[<p style="text-indent: 18pt"><span style="font-family: 宋体">安全永远是</span>WEB<span style="font-family: 宋体">应用系统必须面对的头等大事</span>, <span style="font-family: 宋体">也是最头疼的事</span>, <span style="font-family: 宋体">其实安全系统就只包括两个问题</span>: <span style="font-family: 宋体">认证和授权</span>. <span style="font-family: 宋体">以前做些网站系统</span>, <span style="font-family: 宋体">安全检测逻辑都在放在须要安全控制的代码前面</span>, <span style="font-family: 宋体">这样做有很多不好的地方</span>, <span style="font-family: 宋体">重复多次的编码就不用说了</span>, <span style="font-family: 宋体">代码移植性</span>, <span style="font-family: 宋体">重用性都得不到体现</span>, <span style="font-family: 宋体">安全检测逻辑要永远和业务逻辑放在一起</span>.<span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">那么</span>, <span style="font-family: 宋体">能不能够在进入方法前就调用一些安全检测</span>? <span style="font-family: 宋体">其实</span>Spring AOP<span style="font-family: 宋体">就是这个思想</span>, <span style="font-family: 宋体">那么又如何实现安全检测呢</span>? Spring Acegi Security <span style="font-family: 宋体">框架就是做这个事情。</span>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">本文主要是讨论下在已有的</span>SSH<span style="font-family: 宋体">系统中</span>, <span style="font-family: 宋体">如何使用</span>Acegi<span style="font-family: 宋体">作为安全框架实现基于角色的权限控制</span>(Role Based Access Control RBAC) , <span style="font-family: 宋体">本文主要是以</span>Java 5<span style="font-family: 宋体">注解的形式来配置安全框架</span>, <span style="font-family: 宋体">大大减化配置和操作。</span>&nbsp;</p>
<p style="text-indent: 12pt"><span style="font-family: 宋体">本文的主要参考资料：</span></p>
<p style="text-indent: 36pt">&lt;Spring 2.0 <span style="font-family: 宋体">核心技术与最佳实践</span>&gt; <span style="font-family: 宋体">第</span>10<span style="font-family: 宋体">章</span> (Spring Acegi <span style="font-family: 宋体">安全框架</span>)</p>
<p style="text-indent: 36pt">&lt;<span style="font-family: 宋体">精通</span>Spring 2.X -- <span style="font-family: 宋体">企业应用开发详解</span>&gt; <span style="font-family: 宋体">第</span>17<span style="font-family: 宋体">章</span> (<span style="font-family: 宋体">使用</span>Acegi <span style="font-family: 宋体">实施应用系统安全</span>)</p>
<p style="text-indent: 36pt">acegi-security-1.0.6 <span style="font-family: 宋体">官方文档</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">说明</span>: <span style="font-family: 宋体">本文介绍的是</span>RBAC, <span style="font-family: 宋体">在官方文档的基础上有所扩展或改动</span>, <span style="font-family: 宋体">以更适合</span>WEB<span style="font-family: 宋体">应用系统</span>. <span style="font-family: 宋体">其实我觉得大多数的网站基于角色已经足够了</span>, <span style="font-family: 宋体">一般都没必要基于权限</span>.</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">文章开始</span>:</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">一</span>. <span style="font-family: 宋体">下载所要的软件或</span>JAR<span style="font-family: 宋体">包</span>:</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">我的相关配置是</span>: Java 5, Tomcat 5.5.26, Struts 2.0.11, Spring 2.5.1, Hibernate 3.2, Acegi 1.0.6</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">二</span>. <span style="font-family: 宋体">建立相关的数据库</span>:</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">数据表</span>: <span style="font-family: 宋体">用户信息表</span>User: id, enable, user_name, user_pass, email_box&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">角色信息表</span>RoleInfo: id, role_name, role_title, descp<br /><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">用户与角色关联表</span>(<span style="font-family: 宋体">用户与角色是多对多关系</span>)UserRole: user_id, user_name, role_id, role_name&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">三个表中插入相关的数据</span>, <span style="font-family: 宋体">我是定义了<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;两种角色</span>(role_name): ROLE_USER, ROLE_ADMIN&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体">和三个用户</span>, <span style="font-family: 宋体">一个用户角色为</span>: ROLE_USER, ROLE_ADMIN&nbsp;</p><span style="font-size: 12pt; font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体">另一个用户角色为</span><span style="font-size: 12pt; font-family: 'Times New Roman'">: ROLE_USER<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: 12pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">第三个没有角色</span><span lang="EN-US" style="font-size: 12pt; font-family: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">.
<p><span style="font-family: 宋体">三</span>. <span style="font-family: 宋体">修改配置文件</span>:</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">其实对</span>Acegi<span style="font-family: 宋体">框架的应用难点就在配置文件</span>, <span style="font-family: 宋体">所以要特别注意了</span>:</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在</span> src <span style="font-family: 宋体">建立</span>Acegi<span style="font-family: 宋体">的配置文件</span>: acegi-security.xml <span style="font-family: 宋体">当然这个文件的名称是可以任意的</span>.<span> acegi-security.xml </span><span style="font-family: 宋体">说白了就是配置</span>: <span style="font-family: 宋体">安全拦截器</span>, <span style="font-family: 宋体">认证管理器</span>, <span style="font-family: 宋体">决策管理器</span>.</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">其内容如下</span>:</p>
<p>&nbsp;</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</p>
<p>&lt;beans xmlns=""&gt;</p>
<p>&lt;!------------------------------------ <span style="font-family: 宋体">认证管理器</span> ----------------------&gt;</p>
<p>&lt;bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"&gt;</p>
<p>&lt;property name="providers"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;list&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;ref bean="daoAuthenticationProvider" /&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;ref bean="rememberMeAuthenticationProvider" /&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/list&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;!-- <span style="font-family: 宋体">基于</span>DAO<span style="font-family: 宋体">验证的</span>AuthenticationProvider --&gt;</p>
<p>&lt;bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;</p>
<p>&lt;property name="userDetailsService" ref="userDetailsService" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService"&gt;</p>
<p>&lt;property name="userDao" ref="userDao" /&gt;</p>
<p>&lt;property name="userRoleDao" ref="userRoleDao" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"&gt;</p>
<p>&lt;property name="key" value="" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"&gt;</p>
<p>&lt;property name="userDetailsService" ref="userDetailsService" /&gt;</p>
<p>&lt;property name="parameter" value="j_remember_me" /&gt;</p>
<p>&lt;property name="key" value="obullxl@163.com" /&gt;</p>
<p>&lt;property name="tokenValiditySeconds" value="31536000" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;!-- ========================= <span style="font-family: 宋体">决策管理器</span> ========================= --&gt;</p>
<p>&lt;bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased"&gt;</p>
<p>&lt;property name="decisionVoters"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;list&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;ref bean="roleVoter" /&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/list&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">是否全部弃权就通过</span> --&gt;</p>
<p>&lt;property name="allowIfAllAbstainDecisions" value="false" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter"&gt;</p>
<p>&lt;property name="rolePrefix" value="ROLE_" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;!-- ========================= <span style="font-family: 宋体">过滤器链</span> ========================= --&gt;</p>
<p>&lt;bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"&gt;</p>
<p>&lt;property name="filterInvocationDefinitionSource"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;value&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</span></p>
<p><span>&nbsp;&nbsp;&nbsp; PATTERN_TYPE_APACHE_ANT</span></p>
<p><span>&nbsp;&nbsp;&nbsp; /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter,securityInterceptor</span></p>
<p><span>&nbsp;&nbsp; &lt;/value&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" /&gt;</p>
<p>&lt;bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter"&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">登录退出后的</span>URL --&gt;</p>
<p>&lt;constructor-arg value="/" /&gt;</p>
<p>&lt;constructor-arg&gt;</p>
<p><span>&nbsp;&nbsp; &lt;list&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;ref bean="rememberMeServices" /&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" /&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/list&gt;</span></p>
<p>&lt;/constructor-arg&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">登录退出的</span>URL --&gt;</p>
<p>&lt;property name="filterProcessesUrl" value="/j_logout.j" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"&gt;</p>
<p>&lt;property name="authenticationManager" ref="authenticationManager" /&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">登录失败后的</span>URL --&gt;</p>
<p>&lt;property name="authenticationFailureUrl" value="/login.jsp?msg=%E6%97%A0%E6%95%88%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E6%88%96%E5%8F%A3%E4%BB%A4" /&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">登录成功后的</span>URL --&gt;</p>
<p>&lt;property name="defaultTargetUrl" value="/user/cmd.jsp" /&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">登录的</span>URL --&gt;</p>
<p>&lt;property name="filterProcessesUrl" value="/j_login.j" /&gt;</p>
<p>&lt;property name="rememberMeServices" ref="rememberMeServices" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="rememberMeFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter"&gt;</p>
<p>&lt;property name="authenticationManager" ref="authenticationManager" /&gt;</p>
<p>&lt;property name="rememberMeServices" ref="rememberMeServices" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="exceptionFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">出现</span>AuthenticationException<span style="font-family: 宋体">时的登录入口</span> --&gt;</p>
<p>&lt;property name="authenticationEntryPoint"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;property name="loginFormUrl" value="/login.jsp" /&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;property name="forceHttps" value="false" /&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/bean&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;!-- <span style="font-family: 宋体">出现</span>AccessDeniedException<span style="font-family: 宋体">时的</span>Handler --&gt;</p>
<p>&lt;property name="accessDeniedHandler"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;property name="errorPage" value="/denied.jsp" /&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/bean&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;bean id="securityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;</p>
<p>&lt;property name="authenticationManager" ref="authenticationManager" /&gt;</p>
<p>&lt;property name="accessDecisionManager" ref="accessDecisionManager" /&gt;</p>
<p>&lt;property name="objectDefinitionSource"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;value&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</span></p>
<p><span>&nbsp;&nbsp;&nbsp; PATTERN_TYPE_APACHE_ANT</span></p>
<p><span>&nbsp;&nbsp;&nbsp; /admin/**=ROLE_ADMIN</span></p>
<p><span>&nbsp;&nbsp;&nbsp; /user/**=ROLE_USER</span></p>
<p><span>&nbsp;&nbsp;&nbsp; /cart/previeworder*=ROLE_USER</span></p>
<p><span>&nbsp;&nbsp; &lt;/value&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;/beans&gt;</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在上面的配置文件中</span>, <span style="font-family: 宋体">红色部分要特别注意</span>, <span style="font-family: 宋体">其余的内容都差不多了</span>.</p>
<p>&nbsp;</p>
<p>&lt;bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService"&gt;</p>
<p>&lt;property name="userDao" ref="userDao" /&gt;</p>
<p>&lt;property name="userRoleDao" ref="userRoleDao" /&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在整个应用的安全控制中</span>, <span style="font-family: 宋体">我们唯一要编写代码的类就是</span>: org.ymcn.security.AcegiUserDeitailsService</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">就连登录和登出的代码也不要了</span>.</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">三</span>. <span style="font-family: 宋体">修改</span> web.xml, <span style="font-family: 宋体">增加安全控制过滤链</span>.</p>
<p>&nbsp;</p>
<p>&lt;filter&gt;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;;filter-name&gt;acegiFilterChain&lt;/filter-name&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&lt;param-name&gt;targetClass&lt;/param-name&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;org.acegisecurity.util.FilterChainProxy&lt;/param-value&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;/filter&gt;</span></p>
<p>&nbsp;</p>
<p>&lt;filter-mapping&gt;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;acegiFilterChain&lt;/filter-name&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;*.j&lt;/url-pattern&gt;</span></p>
<p>&lt;/filter-mapping&gt;</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">注意</span>: <span style="font-family: 宋体">这个过滤器一定要在</span>MVC<span style="font-family: 宋体">转发过滤器的前面</span>!!!!</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">四</span>. <span style="font-family: 宋体">在</span> applicationContext.xml <span style="font-family: 宋体">中增加</span> Acegi<span style="font-family: 宋体">安全控制拦截器</span> <span style="font-family: 宋体">和</span> Spring<span style="font-family: 宋体">的自动代理功能实现</span>AOP<span style="font-family: 宋体">代理</span></p>
<p>&nbsp;</p>
<p>&lt;!-- Acegi<span style="font-family: 宋体">安全控制拦截器</span> --&gt;</p>
<p>&lt;bean id="serviceSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;</p>
<p>&lt;property name="validateConfigAttributes" value="true" /&gt;</p>
<p>&lt;property name="authenticationManager" ref="authenticationManager" /&gt;</p>
<p>&lt;property name="accessDecisionManager" ref="accessDecisionManager" /&gt;</p>
<p>&lt;property name="objectDefinitionSource"&gt;</p>
<p>&nbsp;&nbsp;&lt;bean class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"&gt;</p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;property name="attributes"&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean class="org.acegisecurity.annotation.SecurityAnnotationAttributes" /&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/bean&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&lt;!-- <span style="font-family: 宋体">利用</span>Spring<span style="font-family: 宋体">的自动代理功能实现</span>AOP<span style="font-family: 宋体">代理</span> --&gt;</p>
<p>&lt;bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&gt;</p>
<p>&lt;property name="interceptorNames"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;list&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;value&gt;transactionInterceptor&lt;/value&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;value&gt;serviceSecurityInterceptor&lt;/value&gt;</span></p>
<p>&nbsp;&nbsp;&lt;/list&gt;</p>
<p>&lt;/property&gt;</p>
<p>&lt;property name="beanNames"&gt;</p>
<p><span>&nbsp;&nbsp; &lt;list&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;value&gt;userService&lt;/value&gt;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &lt;value&gt;mailService&lt;/value&gt;</span></p>
<p><span>&nbsp;&nbsp; &lt;/list&gt;</span></p>
<p>&lt;/property&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">五</span>. <span style="font-family: 宋体">编写在利用</span>Acegi<span style="font-family: 宋体">框架唯一要我们编写的类</span> AcegiUserDeitailsService.java</p>
<p>&nbsp;</p>
<p>package org.ymcn.security;</p>
<p>&nbsp;</p>
<p>import java.util.List;</p>
<p>&nbsp;</p>
<p>import org.acegisecurity.GrantedAuthority;</p>
<p>import org.acegisecurity.GrantedAuthorityImpl;</p>
<p>import org.acegisecurity.userdetails.UserDetails;</p>
<p>import org.acegisecurity.userdetails.UserDetailsService;</p>
<p>import org.acegisecurity.userdetails.UsernameNotFoundException;</p>
<p>import org.apache.commons.logging.Log;</p>
<p>import org.apache.commons.logging.LogFactory;</p>
<p>import org.springframework.dao.DataAccessException;</p>
<p>import org.ymcn.dao.UserDao;</p>
<p>import org.ymcn.dao.UserRoleDao;</p>
<p>import org.ymcn.model.User;</p>
<p>import org.ymcn.model.UserRole;</p>
<p>&nbsp;</p>
<p>public class AcegiUserDeitailsService implements UserDetailsService {</p>
<p>private final Log LOG = LogFactory.getLog(AcegiUserDeitailsService.class);</p>
<p>/* <span style="font-family: 宋体">依赖注入</span> */</p>
<p>private UserDao userDao;</p>
<p>private UserRoleDao userRoleDao;</p>
<p>&nbsp;</p>
<p>public void setUserDao(UserDao userDao) {</p>
<p><span>&nbsp;&nbsp; this.userDao = userDao;</span></p>
<p>}</p>
<p>public void setUserRoleDao(UserRoleDao userRoleDao) {</p>
<p><span>&nbsp;&nbsp; this.userRoleDao = userRoleDao;</span></p>
<p>}</p>
<p>&nbsp;</p>
<p>/* <span style="font-family: 宋体">用户所有的权限</span> */</p>
<p>//private final List&lt;GrantedAuthority&gt; grantedAuthList = new ArrayList&lt;GrantedAuthority&gt;(6);</p>
<p>private GrantedAuthority[] grantedAuthArray;</p>
<p>&nbsp;</p>
<p>public UserDetails loadUserByUsername(String userName)</p>
<p><span>&nbsp;&nbsp;&nbsp; throws UsernameNotFoundException, DataAccessException {</span></p>
<p><span>&nbsp;&nbsp; if(LOG.isDebugEnabled()) {</span></p>
<p><span>&nbsp;&nbsp;&nbsp; LOG.debug("Loading UserDetails of userName: " + userName);</span></p>
<p><span>&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp; /* </span><span style="font-family: 宋体">取得用户</span> */</p>
<p><span>&nbsp;&nbsp; User user = userDao.getUserByName(userName);</span></p>
<p><span>&nbsp;&nbsp; if(user == null) {</span></p>
<p><span>&nbsp;&nbsp;&nbsp; LOG.warn("UserDetails load failed: No such UserRole with userName: " + userName);</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new UsernameNotFoundException("User name is not found.");</span></p>
<p><span>&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp; /* </span><span style="font-family: 宋体">取得所有用户权限</span> */</p>
<p><span>&nbsp;&nbsp; List&lt;UserRole&gt; userRoleList = userRoleDao.getUserRoleByUserName(userName);</span></p>
<p><span>&nbsp;&nbsp; if(userRoleList == null || userRoleList.size() == 0) {</span></p>
<p><span>&nbsp;&nbsp;&nbsp; LOG.warn("UserRole load failed: No such UserRole with userName: " + userName);</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new UsernameNotFoundException("UserRole is not found.");</span></p>
<p><span>&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp; /* </span><span style="font-family: 宋体">取得用户的所有角色</span> */</p>
<p><span>&nbsp;&nbsp; int size = userRoleList.size();</span></p>
<p><span>&nbsp;&nbsp; grantedAuthArray = new GrantedAuthority[size];</span></p>
<p><span>&nbsp;&nbsp; int j = 0;</span></p>
<p><span>&nbsp;&nbsp; for(int i = 0; i &lt; size; i++) {</span></p>
<p><span>&nbsp;&nbsp;&nbsp; UserRole userRole = userRoleList.get(i);</span></p>
<p><span>&nbsp;&nbsp;&nbsp; if(userRole != null) {</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; this.grantedAuthArray[j++] = new GrantedAuthorityImpl(userRole.getRoleName().toUpperCase());</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp; LOG.info("UserName: " + userName + " loaded successfully.");</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new org.acegisecurity.userdetails.User(userName, user.getUserPass(),</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true, true, true, true, this.grantedAuthArray);</span></p>
<p>}</p>
<p>}</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">六</span>. <span style="font-family: 宋体">在业务逻辑代码中利用</span>Java 5<span style="font-family: 宋体">注释实现安全控制</span></p>
<p>&nbsp;</p>
<p>@Secured({"ROLE_USER"})</p>
<p>void sendSimpleMail(Long userId);</p>
<p>&nbsp;</p>
<p>@Secured({"ROLE_ADMIN"})</p>
<p>void sendAttachmentMail() throws Exception;</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">其实就是在需要安全控制的方法前加上</span>: @Secured({"<span style="font-family: 宋体">角色名</span>"}), <span style="font-family: 宋体">非常的简单</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">七</span>. <span style="font-family: 宋体">整个工作完成</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; Acegi</span><span style="font-family: 宋体">框架完全是一种可插拔式的</span>, <span style="font-family: 宋体">完全可以在原有的系统中加个一个配置文件</span>, <span style="font-family: 宋体">和在每个方法前加上</span>: @Secured({"<span style="font-family: 宋体">角色名</span>"}) <span style="font-family: 宋体">就可完成</span>.</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">上面的</span> AcegiUserDeitailsService.java <span style="font-family: 宋体">中的有</span> UserDao, UserRoleDao, <span style="font-family: 宋体">我想一看就知道它们是干什么的了</span>, <span style="font-family: 宋体">这完全取决于个人的实现</span>, <span style="font-family: 宋体">与</span>Acegi<span style="font-family: 宋体">无关</span>, <span style="font-family: 宋体">它仅仅只要返回一个</span> return new org.acegisecurity.userdetails.User(userName, user.getUserPass(),</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true, true, true, true, this.grantedAuthArray) </span><span style="font-family: 宋体">就可以了</span>.</p><br /><br /></span></span><img src ="http://www.blogjava.net/bracling/aggbug/351887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bracling/" target="_blank">有点抽象</a> 2011-06-07 23:17 <a href="http://www.blogjava.net/bracling/articles/351887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>