Acegi Security 是用于企业 Web 应用程序的一个强大、灵活的安全性解决方案。Acegi 构建在 Java EE 的声明式安全性方法之上,并将 URL 和业务方法许可扩展至任意 Java 对象。Acegi Security 为应用程序提供全面的身份验证、受权、基于实例的访问控制、通道安全和用户验证功能。
如何在现有框架中集成acegi
看了这么牛的介绍,咱们要怎么将acegi和咱们现有系统进行集成呢?
下面以小弟本身弄得一个springMVC框架为例,看看如何一步一步来集成acegi
第一步:JAR包
一如既往,麻烦的jar包(在使用mvn以前我一直为这个很头疼,无止境的冲突),这里我使用的0.9.0版的acegi-security
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security</artifactId>
<version>0.9.0</version>
</dependency>
若是你不是使用的mvn,不要紧,去下载一个好了。http://sourceforge.net/projects/acegisecurity/files/
第二部:配置
若是你不须要特殊的权限配置,基本上来讲,配置就是你使用acegi的所有了:),让咱们来看看怎么配置吧。
beans-acegi-security.xml这个是我配置的acegi信息,你们能够看到已经和Spring集成了.
html
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd" default-autowire="byName"> <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter </value> </property> </bean> <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> <property name="allowSessionCreation" value="false" /> </bean> <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> </list> </property> </bean> <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="usersByUsernameQuery"> <value>SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1</value> </property> <property name="authoritiesByUsernameQuery"> <value>SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1</value> </property> </bean> <bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/> <bean id="acegiUserCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"> <property name="cache" ref="acegiCacheBackend" /> </bean> <bean id="acegiCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref bean="cacheManager"/> </property> <property name="cacheName"> <value>acegiCache</value> </property> </bean> <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref bean="cacheManager"/> </property> <property name="cacheName"> <value>userCache</value> </property> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" > <property name="configLocation"> <value>classpath:/META-INF/config/ehcache.xml</value> </property> </bean> <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="authenticationDao" ref="jdbcDaoImpl" /> <property name="passwordEncoder" ref="passwordEncoder" /> <property name="userCache" ref="acegiUserCache" /> </bean> <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> <property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property> </bean> <bean id="filterInvocationInterceptor" class="net.sf.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 /logon.htm*=ROLE_ANONYMOUS,ROLE_USER /index.htm*=ROLE_ANONYMOUS,ROLE_USER /register.htm*=ROLE_ANONYMOUS,ROLE_USER /dwr/**=ROLE_ANONYMOUS,ROLE_USER /service/**=ROLE_ANONYMOUS,ROLE_USER /**=ROLE_USER </value> </property> </bean> <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"> <property name="allowIfAllAbstainDecisions"><value>false</value></property> <property name="decisionVoters"> <list> <ref bean="roleVoter"/> </list> </property> </bean> <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationFailureUrl"><value>/logon.htm?login_error=1</value></property> <property name="defaultTargetUrl"><value>/index.htm</value></property> <property name="filterProcessesUrl"><value>/user_login.htm</value></property> <property name="rememberMeServices"><ref bean="rememberMeServices"/></property> </bean> <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl"><value>/logon.htm</value></property> <property name="forceHttps"><value>false</value></property> </bean> <bean id="rememberMeServices" class="net.sf.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"> <property name="tokenValiditySeconds" value="432000"/> <property name="key" value="springRocks" /> <property name="authenticationDao" ref="jdbcDaoImpl" /> </bean> <bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> <property name="key" value="anonymous" /> <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS" /> </bean> </beans>
18个类的定义就支撑起了咱们的acegi安全框架,不得不赞叹下acegi的牛人啊!
简单说明下,若是须要更加具体的说明能够google,也能够去看下http://www.springside.org.cn/docs/reference/Acegi3.htm这里介绍得比较详细,不像兰色说不清楚,嘿嘿!java
filterChainProxy:是经过一个标准的FilterInvocationDefinitionSource 来实现配置的,在这个类下面有filterInvocationDefinitionSource配置项目,里面定义了一个过滤器的链,这决定了咱们在页面上进行的任何一次请求均会通过这个过滤器链中全部过滤器的处理:)我定义的链比较简单,就是用了httpSessionContextIntegrationFilter、authenticationProcessingFilter、anonymousProcessingFilter、securityEnforcementFilter四个过滤器,还有不少acegi过滤器就不一一列出了,有兴趣的同窗能够本身去参考一下其余网络资料或者书籍进行学习哦!
httpSessionContextIntegrationFilter:在多个请求之间共享SecurityContext,若是存在则必须放在过滤器链的第一位。用户认证后负责从Session中获取用户关联的SecurityContext存放到SecurityContextHolder,每一个请求都会有SecurityContextHolder用来保存着SecurityContext,而SecurityContext又保存了包含acegi认证重要信息的Authentication对象。
authenticationProcessingFilter:使用认证处理过滤器处理匹配的URL,这里定义你的登陆页面,成功跳转页面和失败页面,还能够设置是否须要记录登陆状态等。
anonymousProcessingFilter:匿名用户处理。若是用户还没有登陆,将生成一个匿名用户的Authentication存放到SecurityContext中
securityEnforcementFilter:强制安全验证过滤器。验证所请求的url是否在用户的权限范围内web
第二部:数据库绑定spring
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> </list> </property> </bean> <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="authenticationDao" ref="jdbcDaoImpl" /> <property name="passwordEncoder" ref="passwordEncoder" /> <property name="userCache" ref="acegiUserCache" /> </bean> <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="usersByUsernameQuery"> <value>SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1</value> </property> <property name="authoritiesByUsernameQuery"> <value>SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1</value> </property> </bean> <bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
上面的配置中,咱们设置了认证数据是由数据库提供的,而且启用了MD5对密码进行加密和缓存,而后咱们还能够看到两条sql语句。
SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1
SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1
这个是最基本的acegi的认证方式,须要提供的内容有
用户信息:包括username(用户名),password(密码),enabled(开启状态)
认证信息:包括username(登录名),authority(认证级别)
(上面的英文列名若是不扩展的话必须是同样的哦,若是你当前数据库中的字段名称不同,请用as语句转换一下才能用)
这个时候acegi就知道数据库中咱们的用户信息及权限级别了:)sql
第三步 那acegi怎么控制用户访问呢?
数据库
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> <property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property> </bean> <bean id="filterInvocationInterceptor" class="net.sf.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 /logon.htm*=ROLE_ANONYMOUS,ROLE_USER /index.htm*=ROLE_ANONYMOUS,ROLE_USER /register.htm*=ROLE_ANONYMOUS,ROLE_USER /dwr/**=ROLE_ANONYMOUS,ROLE_USER /service/**=ROLE_ANONYMOUS,ROLE_USER /**=ROLE_USER </value> </property> </bean> <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"> <property name="allowIfAllAbstainDecisions"><value>false</value></property> <property name="decisionVoters"> <list> <ref bean="roleVoter"/> </list> </property> </bean> <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> <bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> <property name="key" value="anonymous" /> <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS" /> </bean>
哈,上面的就是最基本的acegi的认证投票了,咱们定义了一个反问URL角色过滤器用来告诉acegi访问url时候须要使用什么角色,用了一个投票器告诉acegi处理访问用户须要使用默认的ROLE_开头,从配置总咱们能够看到两种角色ROLE_ANONYMOUS、ROLE_USER,对应authority(认证级别)中存放的内容哦,还有一种ROLE_ANONYMOUS,这个是默认任何人均可以访问的。缓存
第四步 都配好了,怎么登录?
安全
<bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationFailureUrl"><value>/logon.htm?login_error=1</value></property> <property name="defaultTargetUrl"><value>/index.htm</value></property> <property name="filterProcessesUrl"><value>/user_login.htm</value></property> <property name="rememberMeServices"><ref bean="rememberMeServices"/></property> </bean> <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl"><value>/logon.htm</value></property> <property name="forceHttps"><value>false</value></property> </bean>
哈哈,有不少url页面了!
filterProcessesUrl:用于认证的action
defaultTargetUrl投票认证成功后跳转页面
authenticationFailureUrl:投票认证失败后跳转页面
loginFormUrl:认证失效用户重定向到登录的表单url
如今页面url也配置好了,让咱们再看看登录页面里面有什么呢?
网络
<form action="user_login.htm" method="post"> <table border="1px" cellpadding="1" cellspacing="1" style="text-align: center"> #if($errMsg) <tr> <td colspan="3"><style color="red">$errMsg</style></td> </tr> #end <tr> <td>用户名:</td> <td><input type="text" name="j_username"></td> <td> </td> </tr> <tr> <td>密 码:</td> <td><input type="password" name="j_password"></td> <td> </td> </tr><tr> <td> </td> <td><input id="submit" type="submit" value="登陆" name="submit" /> <input id="submit" type="button" value="注册" name="register" onClick="location.href='register.htm'"/></td> <td> </td> </tr> </table> </form>
一个form就搞定了,action是刚才咱们配置的地址,用户名和用户密码是默认的j_username,j_password这样就能够完成咱们的登陆了,你们能够是尝试一下
app