- 浏览: 169591 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
why240829544:
谢谢
Spring Security 2.0.x中文参考文档.pdf -
lzc879141573:
...
Spring Security 2.0.x中文参考文档.pdf -
zpl:
C:\Documents and Settings\Admin ...
导入word到Fckeditor(java实现) -
zpl:
[img][/img] asdfasdfasdfa
导入word到Fckeditor(java实现) -
zhoutao.temp:
Java文件下载的几种方式
安全永远是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 说白了就是配置: 安全拦截器, 认证管理器, 决策管理器.
其内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="">
<!-- ========================= 认证管理器 ========================= -->
<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="" />
</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>
在上面的配置文件中, 红色部分要特别注意, 其余的内容都差不多了.
<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) 就可以了.
祝大家使用JAVA愉快!!!
发表评论
-
spring+hibernate的clob大字段处理
2008-12-26 10:46 2617spring+hibernate的clob大字 ... -
spring执行定时任务之二<触发器配置>
2008-12-26 10:44 4101关于简单触发器和复杂触发器,查考下面的解释: Quartz设计 ... -
spring执行定时任务之一<示例>
2008-12-26 10:27 1039spring执行定时任务 定义一个任务是很简单 ... -
Spring Security-2.0.x参考文档“安全数据库表结构”
2008-10-22 21:48 1526安全数据库表结构 可以为框架采用不同的数据库结构,这个附录为所 ... -
Spring Security 2.0.x中文参考文档.pdf
2008-10-19 23:27 14150一个很好的中文Spring Security 2.0.x中文参 ... -
acegi到spring security的转换方式
2008-10-18 22:35 1239作者 Chris.Baker,发表于 2008 ... -
利用TransactionProxyFactoryBean生成事务代理
2008-10-17 23:31 1839通常建议采用声明式事 ... -
Spring管理事务的若干配置形式
2008-10-17 23:29 1117虽说利用Spring来实现配置式事务的基本原理都是AOP,但其 ... -
spring声明式事务管理的两种方式
2008-10-17 23:24 1149传统的: 1 <bean id="d ... -
Struts与Spring整合的第四种方法
2008-10-15 20:29 989论坛中用Struts+Spring的人不少,以前的帖子也有问过 ... -
使用 Spring 更好地处理 Struts 动作
2008-10-15 20:15 832使用 Spring 更好地处理 Struts 动作 三 ...
相关推荐
Acegi是一个可插拔框架,主要是在SSH框架上插入Acegi安全框架。
struts + spring + hibernate + velocity + ajax + jotm + acegi
Struts2+Spring+Hibernate3+Acegi,对Acegi进行了扩展, 可直接在Myeclipse6.0.1下直接运行通过,
Struts2.0+spring2.0+hibernate3.1 ACEGI应用示例
Acegi_Spring_Hibernate_Struts2搭建基于角色的权限控制系统.doc
該示例采用Strtus+Spring+Hibernate(簡稱SSH組合)實現一個簡單的電子公告板示例,演示了SSH組合在WEB中的一般應用,在這裡可以體驗到SSH組合清暫的分層,代碼簡潔清楚,各類文件之間的關係變得不再復雜了。...
在安全方面集成Spring的安全框架Acegi和最流行的Ajax技术。与其他框架相比,它提供了各种Web系统开发过程中都需要开发的一些功能,如登陆、用户密码加密,用户管理、根据不同的用户可以展现不同的菜单,同时还带有...
spring+hibernate+struts+acegi+mysql实现,完整程序,包括前台、用户中心、后台,可以直接在tomcat下运行。数据库的表通过hibernate动态生成。此程序是我自己开发的,里面涉及到文件上传、分页、fckeditor编辑器、...
本系统有更新版本,请用关键字struts spring hibernate acegi jotm等搜索新版本
本文介绍open-JWeb(RAD)开发平台,此平台基于Spring+hibernate+struts+webwork+acegi+dwr技术,内容包括动态生成增删改查功能(含分页,查询,编辑等),无需编程即可实现.另外集成了强大的acegi框架,及基于FCKEDIT的信息...
11.2.4 基于Acegi和Yale CAS实现单次登录 11.3 控制访问 11.3.1 访问决策投票 11.3.2 决定如何投票 11.3.3 处理投票弃权 11.4 保护Web应用程序 11.4.1 代理Acegi的过滤器 11.4.2 ...
Java 6 RowSet 使用完全剖析 结合Spring2.0和ActiveMQ进行异步消息调用 struts+hibernate增删改查(一) AXIS 布署问题 struts+hibernate增删改查(二) MySQL中如何实现Top N及M至N段的记录查询?...
Ext2.1,Struts1.3,Hibernate3.2,Spring2.5,Acegi 1.06,MySQL 2.功能概述: Blog,RSS订阅,网址导航 3.特色 基于标准的SSH结构,基础Ext的展现界面,基于数据库的acegi安全认证.可随意更改的portal布局,可随意添加的...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
常見程式演算,電腦圖學入門,設計模式,C 語言,GTK,C++,Qt3,Qt4,,Java (上),Java (下),JSP/Servlet,JSF,Ajax,JUnit,Struts,Spring,Hibernate,Acegi
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...