- 浏览: 242406 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
xchd:
分别在什么时候(情况下)用ThreadFactory、Exec ...
Executor线程池实例 -
mikey_5:
是不是没有写完啊
Executor线程池实例 -
xinyao:
楼主,你好,请问能给我发个源码吗,我要在一个页面能实时看到下载 ...
Android学习系列(19)--App离线下载 -
sdtzkj:
...
jasperReport 帮助文档 api -
shero_ys:
public class VrowsePicActivity ...
android handler 实现三步曲
安全永远是WEB应用系统必须面对的头等大事, 也是最头疼的事, 其实安全系统就只包括两个问题: 认证和授权.
以前做些网站系统, 安全检测逻辑都在放在须要安全控制的代码前面, 这样做有很多不好的地方, 重复多次的编码就不用说了, 代码移植性, 重用性都得不到体现, 安全检测逻辑要永远和业务逻辑放在一起.
那么, 能不能够在进入方法前就调用一些安全检测? 其实Spring AOP就是这个思想, 那么又如何实现安全检测呢? Spring Acegi Security 框架就是做这个事情.
本文主要是讨论下在已有的SSH系统中, 如何使用Acegi作为安全框架实现基于角色的权限控制(Role Based Access Control RBAC) , 本文主要是以Java 5注解的形式来配置安全框架, 大大减化配置和操作.
本文的主要参考资料: <Spring 2.0 核心技术与最佳实践> 第10章 (Spring Acegi 安全框架)
<精通Spring 2.X -- 企业应用开发详解> 第17章 (使用Acegi 实施应用系统安全)
acegi-security-1.0.6 官方文档
说明: 本文介绍的是RBAC, 在官方文档的基础上有所扩展或改动, 以更适合WEB应用系统. 其实我觉得大多数的网站基于角色已经足够了, 一般都没必要基于权限.
文章开始:
一. 下载所要的软件或JAR包:
我的相关配置是: Java 5, Tomcat 5.5.26, Struts 2.0.11, Spring 2.5.1, Hibernate 3.2, Acegi 1.0.6
二. 建立相关的数据库:
数据表: 用户信息表User: id, enable, user_name, user_pass, email_box
角色信息表RoleInfo: id, role_name, role_title, descp
用户与角色关联表(用户与角色是多对多关系)UserRole: user_id, user_name, role_id, role_name
并在这三个表中插入相关的数据, 我是定义了两种角色(role_name): ROLE_USER, ROLE_ADMIN
和三个用户, 一个用户角色为: ROLE_USER, ROLE_ADMIN
另一个用户角色为: ROLE_USER
第三个没有角色.
二. 修改配置文件:
其实对Acegi框架的应用难点就在配置文件, 所以要特别注意了:
在 src 建立Acegi的配置文件: acegi-security.xml 当然这个文件的名称是可以任意的.
acegi-security.xml 说白了就是配置: 安全拦截器, 认证管理器, 决策管理器.
其内容如下:
在上面的配置文件中, 红色部分要特别注意, 其余的内容都差不多了.
在整个应用的安全控制中, 我们唯一要编写代码的类就是: org.ymcn.security.AcegiUserDeitailsService
就连登录和登出的代码也不要了.
三. 修改 web.xml, 增加安全控制过滤链.
<!-- 利用Spring的自动代理功能实现AOP代理 -->
六. 在业务逻辑代码中利用Java 5注释实现安全控制
其实就是在需要安全控制的方法前加上: @Secured({"角色名"}), 非常的简单
七. 整个工作完成
Acegi框架完全是一种可插拔式的, 完全可以在原有的系统中加个一个配置文件, 和在每个方法前加上: @Secured({"角色名"}) 就可完成.
上面的 AcegiUserDeitailsService.java 中的有 UserDao, UserRoleDao, 我想一看就知道它们是干什么的了, 这完全取决于个人的实现, 与Acegi无关, 它仅仅只要返回一个 return new org.acegisecurity.userdetails.User(userName, user.getUserPass(),
true, true, true, true, this.grantedAuthArray) 就可以了.
以前做些网站系统, 安全检测逻辑都在放在须要安全控制的代码前面, 这样做有很多不好的地方, 重复多次的编码就不用说了, 代码移植性, 重用性都得不到体现, 安全检测逻辑要永远和业务逻辑放在一起.
那么, 能不能够在进入方法前就调用一些安全检测? 其实Spring AOP就是这个思想, 那么又如何实现安全检测呢? Spring Acegi Security 框架就是做这个事情.
本文主要是讨论下在已有的SSH系统中, 如何使用Acegi作为安全框架实现基于角色的权限控制(Role Based Access Control RBAC) , 本文主要是以Java 5注解的形式来配置安全框架, 大大减化配置和操作.
本文的主要参考资料: <Spring 2.0 核心技术与最佳实践> 第10章 (Spring Acegi 安全框架)
<精通Spring 2.X -- 企业应用开发详解> 第17章 (使用Acegi 实施应用系统安全)
acegi-security-1.0.6 官方文档
说明: 本文介绍的是RBAC, 在官方文档的基础上有所扩展或改动, 以更适合WEB应用系统. 其实我觉得大多数的网站基于角色已经足够了, 一般都没必要基于权限.
文章开始:
一. 下载所要的软件或JAR包:
我的相关配置是: Java 5, Tomcat 5.5.26, Struts 2.0.11, Spring 2.5.1, Hibernate 3.2, Acegi 1.0.6
二. 建立相关的数据库:
数据表: 用户信息表User: id, enable, user_name, user_pass, email_box
角色信息表RoleInfo: id, role_name, role_title, descp
用户与角色关联表(用户与角色是多对多关系)UserRole: user_id, user_name, role_id, role_name
并在这三个表中插入相关的数据, 我是定义了两种角色(role_name): ROLE_USER, ROLE_ADMIN
和三个用户, 一个用户角色为: ROLE_USER, ROLE_ADMIN
另一个用户角色为: ROLE_USER
第三个没有角色.
二. 修改配置文件:
其实对Acegi框架的应用难点就在配置文件, 所以要特别注意了:
在 src 建立Acegi的配置文件: acegi-security.xml 当然这个文件的名称是可以任意的.
acegi-security.xml 说白了就是配置: 安全拦截器, 认证管理器, 决策管理器.
其内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="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.xsd"> <!-- ========================= 认证管理器 ========================= --> <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> <ref bean="rememberMeAuthenticationProvider" /> </list> </property> </bean> <!-- 基于DAO验证的AuthenticationProvider --> <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDetailsService" /> </bean> <bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService"> <property name="userDao" ref="userDao" /> <property name="userRoleDao" ref="userRoleDao" /> </bean> <bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"> <property name="key" value="obullxl@163.com" /> </bean> <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"> <property name="userDetailsService" ref="userDetailsService" /> <property name="parameter" value="j_remember_me" /> <property name="key" value="obullxl@163.com" /> <property name="tokenValiditySeconds" value="31536000" /> </bean> <!-- ========================= 决策管理器 ========================= --> <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased"> <property name="decisionVoters"> <list> <ref bean="roleVoter" /> </list> </property> <!-- 是否全部弃权就通过 --> <property name="allowIfAllAbstainDecisions" value="false" /> </bean> <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter"> <property name="rolePrefix" value="ROLE_" /> </bean> <!-- ========================= 过滤器链 ========================= --> <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter,securityInterceptor </value> </property> </bean> <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" /> <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter"> <!-- 登录退出后的URL --> <constructor-arg value="/" /> <constructor-arg> <list> <ref bean="rememberMeServices" /> <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" /> </list> </constructor-arg> <!-- 登录退出的URL --> <property name="filterProcessesUrl" value="/j_logout.j" /> </bean> <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <!-- 登录失败后的URL --> <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" /> <!-- 登录成功后的URL --> <property name="defaultTargetUrl" value="/user/cmd.jsp" /> <!-- 登录的URL --> <property name="filterProcessesUrl" value="/j_login.j" /> <property name="rememberMeServices" ref="rememberMeServices" /> </bean> <bean id="rememberMeFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <property name="rememberMeServices" ref="rememberMeServices" /> </bean> <bean id="exceptionFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> <!-- 出现AuthenticationException时的登录入口 --> <property name="authenticationEntryPoint"> <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/login.jsp" /> <property name="forceHttps" value="false" /> </bean> </property> <!-- 出现AccessDeniedException时的Handler --> <property name="accessDeniedHandler"> <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"> <property name="errorPage" value="/denied.jsp" /> </bean> </property> </bean> <bean id="securityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /admin/**=ROLE_ADMIN /user/**=ROLE_USER /cart/previeworder*=ROLE_USER </value> </property> </bean> </beans>
在上面的配置文件中, 红色部分要特别注意, 其余的内容都差不多了.
- userRoleDao" ref="userRoleDao" />
- </bean>
<bean id="userDetailsService" class="org.ymcn.security.AcegiUserDeitailsService"> <property name="userDao" ref="userDao" /> <property name="userRoleDao" ref="userRoleDao" /> </bean>
在整个应用的安全控制中, 我们唯一要编写代码的类就是: org.ymcn.security.AcegiUserDeitailsService
就连登录和登出的代码也不要了.
三. 修改 web.xml, 增加安全控制过滤链.
<filter> <filter-name>acegiFilterChain</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter-mapping> <filter-name>acegiFilterChain</filter-name> <url-pattern>*.j</url-pattern> </filter-mapping> 注意: 这个过滤器一定要在MVC转发过滤器的前面!!!! 四. 在 applicationContext.xml 中增加 Acegi安全控制拦截器 和 Spring的自动代理功能实现AOP代理 <!-- Acegi安全控制拦截器 --> <bean id="serviceSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> <property name="validateConfigAttributes" value="true" /> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <bean class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> <property name="attributes"> <bean class="org.acegisecurity.annotation.SecurityAnnotationAttributes" /> </property> </bean> </property> </bean>
<!-- 利用Spring的自动代理功能实现AOP代理 -->
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> <value>serviceSecurityInterceptor</value> </list> </property> <property name="beanNames"> <list> <value>userService</value> <value>mailService</value> </list> </property> </bean> 五. 编写在利用Acegi框架唯一要我们编写的类 AcegiUserDeitailsService.java package org.ymcn.security; import java.util.List; import org.acegisecurity.GrantedAuthority; import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessException; import org.ymcn.dao.UserDao; import org.ymcn.dao.UserRoleDao; import org.ymcn.model.User; import org.ymcn.model.UserRole; public class AcegiUserDeitailsService implements UserDetailsService { private final Log LOG = LogFactory.getLog(AcegiUserDeitailsService.class); /* 依赖注入 */ private UserDao userDao; private UserRoleDao userRoleDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setUserRoleDao(UserRoleDao userRoleDao) { this.userRoleDao = userRoleDao; } /* 用户所有的权限 */ //private final List<GrantedAuthority> grantedAuthList = new ArrayList<GrantedAuthority>(6); private GrantedAuthority[] grantedAuthArray; public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException { if(LOG.isDebugEnabled()) { LOG.debug("Loading UserDetails of userName: " + userName); } /* 取得用户 */ User user = userDao.getUserByName(userName); if(user == null) { LOG.warn("UserDetails load failed: No such UserRole with userName: " + userName); throw new UsernameNotFoundException("User name is not found."); } /* 取得所有用户权限 */ List<UserRole> userRoleList = userRoleDao.getUserRoleByUserName(userName); if(userRoleList == null || userRoleList.size() == 0) { LOG.warn("UserRole load failed: No such UserRole with userName: " + userName); throw new UsernameNotFoundException("UserRole is not found."); } /* 取得用户的所有角色 */ int size = userRoleList.size(); grantedAuthArray = new GrantedAuthority[size]; int j = 0; for(int i = 0; i < size; i++) { UserRole userRole = userRoleList.get(i); if(userRole != null) { this.grantedAuthArray[j++] = new GrantedAuthorityImpl(userRole.getRoleName().toUpperCase()); } } LOG.info("UserName: " + userName + " loaded successfully."); return new org.acegisecurity.userdetails.User(userName, user.getUserPass(), true, true, true, true, this.grantedAuthArray); } }
六. 在业务逻辑代码中利用Java 5注释实现安全控制
@Secured({"ROLE_USER"}) void sendSimpleMail(Long userId); @Secured({"ROLE_ADMIN"}) void sendAttachmentMail() throws Exception;
其实就是在需要安全控制的方法前加上: @Secured({"角色名"}), 非常的简单
七. 整个工作完成
Acegi框架完全是一种可插拔式的, 完全可以在原有的系统中加个一个配置文件, 和在每个方法前加上: @Secured({"角色名"}) 就可完成.
上面的 AcegiUserDeitailsService.java 中的有 UserDao, UserRoleDao, 我想一看就知道它们是干什么的了, 这完全取决于个人的实现, 与Acegi无关, 它仅仅只要返回一个 return new org.acegisecurity.userdetails.User(userName, user.getUserPass(),
true, true, true, true, this.grantedAuthArray) 就可以了.
<script type="text/javascript"></script><script src="http://a.alimama.cn/inf.js" type="text/javascript"></script>
发表评论
-
在Spring与Hibernate和Struts的整合 各起作用
2010-12-08 13:23 1805框架层次结构层次分为四层:表现层、持久层、业务层、域对象层。每 ... -
详解spring2.0的scope
2010-03-08 16:45 991如何使用spring的作用域 ... -
spring AOP
2010-02-04 10:38 1405一、AOP 概念 Joinpoint: ... -
spring IOC
2010-02-04 10:21 1159IoC与DI 首先想说说 ... -
spring事务管理
2010-02-04 09:58 2087数据库事务的4个特性: 一致性(consi ... -
Spring中bean的作用域详解
2010-02-04 09:38 1146在spring2.0之前bean只有2种作用域即:single ... -
spring 事务 及spring作用
2010-02-04 08:52 2364spring 作用:Ioc依赖注入,事务管理。 还有就是AOP ... -
spring 优化
2010-02-03 15:39 926WEB上主要还是容器和数据库上的优化。比如:tomcat和ap ... -
spring 单例模式
2010-01-21 08:52 2804单例模式也属于创建型模式,所谓单例,顾名思义,所指的就是单个实 ...
相关推荐
内容概要:本文详细介绍了基于MATLAB GUI界面和卷积神经网络(CNN)的模糊车牌识别系统。该系统旨在解决现实中车牌因模糊不清导致识别困难的问题。文中阐述了整个流程的关键步骤,包括图像的模糊还原、灰度化、阈值化、边缘检测、孔洞填充、形态学操作、滤波操作、车牌定位、字符分割以及最终的字符识别。通过使用维纳滤波或最小二乘法约束滤波进行模糊还原,再利用CNN的强大特征提取能力完成字符分类。此外,还特别强调了MATLAB GUI界面的设计,使得用户能直观便捷地操作整个系统。 适合人群:对图像处理和深度学习感兴趣的科研人员、高校学生及从事相关领域的工程师。 使用场景及目标:适用于交通管理、智能停车场等领域,用于提升车牌识别的准确性和效率,特别是在面对模糊车牌时的表现。 其他说明:文中提供了部分关键代码片段作为参考,并对实验结果进行了详细的分析,展示了系统在不同环境下的表现情况及其潜在的应用前景。
嵌入式八股文面试题库资料知识宝典-计算机专业试题.zip
嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_3.zip
内容概要:本文深入探讨了一款额定功率为4kW的开关磁阻电机,详细介绍了其性能参数如额定功率、转速、效率、输出转矩和脉动率等。同时,文章还展示了利用RMxprt、Maxwell 2D和3D模型对该电机进行仿真的方法和技术,通过外电路分析进一步研究其电气性能和动态响应特性。最后,文章提供了基于RMxprt模型的MATLAB仿真代码示例,帮助读者理解电机的工作原理及其性能特点。 适合人群:从事电机设计、工业自动化领域的工程师和技术人员,尤其是对开关磁阻电机感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解开关磁阻电机特性和建模技术的研究人员,在新产品开发或现有产品改进时作为参考资料。 其他说明:文中提供的代码示例仅用于演示目的,实际操作时需根据所用软件的具体情况进行适当修改。
少儿编程scratch项目源代码文件案例素材-剑客冲刺.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
内容概要:本文详细介绍了基于PID控制器的四象限直流电机速度驱动控制系统仿真模型及其永磁直流电机(PMDC)转速控制模型。首先阐述了PID控制器的工作原理,即通过对系统误差的比例、积分和微分运算来调整电机的驱动信号,从而实现转速的精确控制。接着讨论了如何利用PID控制器使有刷PMDC电机在四个象限中精确跟踪参考速度,并展示了仿真模型在应对快速负载扰动时的有效性和稳定性。最后,提供了Simulink仿真模型和详细的Word模型说明文档,帮助读者理解和调整PID控制器参数,以达到最佳控制效果。 适合人群:从事电力电子与电机控制领域的研究人员和技术人员,尤其是对四象限直流电机速度驱动控制系统感兴趣的读者。 使用场景及目标:适用于需要深入了解和掌握四象限直流电机速度驱动控制系统设计与实现的研究人员和技术人员。目标是在实际项目中能够运用PID控制器实现电机转速的精确控制,并提高系统的稳定性和抗干扰能力。 其他说明:文中引用了多篇相关领域的权威文献,确保了理论依据的可靠性和实用性。此外,提供的Simulink模型和Word文档有助于读者更好地理解和实践所介绍的内容。
嵌入式八股文面试题库资料知识宝典-2013年海康威视校园招聘嵌入式开发笔试题.zip
少儿编程scratch项目源代码文件案例素材-驾驶通关.zip
小区开放对周边道路通行能力影响的研究.pdf
内容概要:本文探讨了冷链物流车辆路径优化问题,特别是如何通过NSGA-2遗传算法和软硬时间窗策略来实现高效、环保和高客户满意度的路径规划。文中介绍了冷链物流的特点及其重要性,提出了软时间窗概念,允许一定的配送时间弹性,同时考虑碳排放成本,以达到绿色物流的目的。此外,还讨论了如何将客户满意度作为路径优化的重要评价标准之一。最后,通过一段简化的Python代码展示了遗传算法的应用。 适合人群:从事物流管理、冷链物流运营的专业人士,以及对遗传算法和路径优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于冷链物流企业,旨在优化配送路线,降低运营成本,减少碳排放,提升客户满意度。目标是帮助企业实现绿色、高效的物流配送系统。 其他说明:文中提供的代码仅为示意,实际应用需根据具体情况调整参数设置和模型构建。
少儿编程scratch项目源代码文件案例素材-恐怖矿井.zip
内容概要:本文详细介绍了基于STM32F030的无刷电机控制方案,重点在于高压FOC(磁场定向控制)技术和滑膜无感FOC的应用。该方案实现了过载、过欠压、堵转等多种保护机制,并提供了完整的源码、原理图和PCB设计。文中展示了关键代码片段,如滑膜观测器和电流环处理,以及保护机制的具体实现方法。此外,还提到了方案的移植要点和实际测试效果,确保系统的稳定性和高效性。 适合人群:嵌入式系统开发者、电机控制系统工程师、硬件工程师。 使用场景及目标:适用于需要高性能无刷电机控制的应用场景,如工业自动化设备、无人机、电动工具等。目标是提供一种成熟的、经过验证的无刷电机控制方案,帮助开发者快速实现并优化电机控制性能。 其他说明:提供的资料包括详细的原理图、PCB设计文件、源码及测试视频,方便开发者进行学习和应用。
基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf
嵌入式八股文面试题库资料知识宝典-CC++笔试题-深圳有为(2019.2.28)1.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 V1.5.zip
Android系统开发_Linux内核配置_USB-HID设备模拟_通过root权限将Android设备转换为全功能USB键盘的项目实现_该项目需要内核支持configFS文件系统
C# WPF - LiveCharts Project
少儿编程scratch项目源代码文件案例素材-恐怖叉子 动画.zip
嵌入式八股文面试题库资料知识宝典-嵌⼊式⼯程师⾯试⾼频问题.zip