﻿<?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-渔人码头-文章分类-Spring</title><link>http://www.blogjava.net/fisher/category/17937.html</link><description>天行健，君子以自强不息。地势坤，君子以厚德载物。</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:43:55 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:43:55 GMT</pubDate><ttl>60</ttl><item><title>用Acegi为你的Spring应用加把锁！(转)</title><link>http://www.blogjava.net/fisher/articles/92379.html</link><dc:creator>Fisher</dc:creator><author>Fisher</author><pubDate>Mon, 08 Jan 2007 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/fisher/articles/92379.html</guid><wfw:comment>http://www.blogjava.net/fisher/comments/92379.html</wfw:comment><comments>http://www.blogjava.net/fisher/articles/92379.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fisher/comments/commentRss/92379.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fisher/services/trackbacks/92379.html</trackback:ping><description><![CDATA[
		<div class="Tag">
				<script language="javascript" src="http://tag.csdn.net/urltag.aspx">
				</script>
		</div>
		<div class="post">
				<div class="postText">
						<font size="3">
								<font color="#0000ff">
										<b>[简介]</b>
								</font>
								<br />
								<font size="2">对于一个典型的Web应用，完善的认证和授权机制是必不可少的，在SpringFramework中，Juergen Hoeller提供的范例JPetStore给了一些这方面的介绍，但还远远不够，Acegi是一个专门为SpringFramework提供安全机制的 项目，全称为Acegi Security System for Spring，当前版本为0.5.1，就其目前提供的功能，应该可以满足绝大多数应用的需求。<br /><br />本文的主要目的是希望能够说明如何在基于Spring构架的Web应用中使用Acegi，而不是详细介绍其中的每个接口、每个类。注意，即使对已经存在的Spring应用，通过下面介绍的步骤，也可以马上享受到Acegi提供的认证和授权。</font>
								<br />
								<font color="#0000ff">
										<br />
										<b>[基础工作]</b>
								</font>
								<br />
								<font size="2">在你的Web应用的lib中添加Acegi下载包中的acegi-security.jar</font>
								<br />
								<br />
								<font color="#0000ff">
										<b>[web.xml]</b>
								</font>
								<br />
								<font size="2">实现认证和授权的最常用的方法是通过filter，Acegi亦是如此，通常Acegi需要在web.xml添加以下5个filter:</font>
								<br />
								<font size="2">
										<br />
										<font color="#800080">&lt;filter&gt;<br />  &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt;<br />  &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;<br />  &lt;init-param&gt;<br />    &lt;param-name&gt;targetClass&lt;/param-name&gt;<br />    &lt;param-value&gt;net.sf.acegisecurity.securechannel.ChannelProcessingFilter&lt;/param-value&gt;<br />  &lt;/init-param&gt;<br />&lt;/filter&gt;<br />&lt;filter&gt;<br />  &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;<br />  &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;<br />  &lt;init-param&gt;<br />    &lt;param-name&gt;targetClass&lt;/param-name&gt;<br />    &lt;param-value&gt;net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter&lt;/param-value&gt;<br />  &lt;/init-param&gt;<br />&lt;/filter&gt;<br />&lt;filter&gt;<br />  &lt;filter-name&gt;Acegi HTTP BASIC Authorization Filter&lt;/filter-name&gt;<br />  &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;<br />  &lt;init-param&gt;<br />    &lt;param-name&gt;targetClass&lt;/param-name&gt;<br />    &lt;param-value&gt;net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter&lt;/param-value&gt;<br />  &lt;/init-param&gt;<br />&lt;/filter&gt;<br />&lt;filter&gt;<br />  &lt;filter-name&gt;Acegi Security System for Spring Auto Integration Filter&lt;/filter-name&gt;<br />  &lt;filter-class&gt;net.sf.acegisecurity.ui.AutoIntegrationFilter&lt;/filter-class&gt;<br />&lt;/filter&gt;<br />&lt;filter&gt;<br />  &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt;<br />  &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;<br />  &lt;init-param&gt;<br />    &lt;param-name&gt;targetClass&lt;/param-name&gt;<br />    &lt;param-value&gt;net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter&lt;/param-value&gt;<br />  &lt;/init-param&gt;<br />&lt;/filter&gt;<br /></font>
										<br />最先引起迷惑的是net.sf.acegisecurity.util.FilterToBeanProxy，Acegi自己的文档上解释是： “What  FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the <br />Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility.”，如希望深究的话，去看看源代码应该不难理解。<br /><br />再下来就是添加filter-mapping了：<br /><font color="#800080">&lt;filter-mapping&gt;<br />  &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt;<br />  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />&lt;filter-mapping&gt;<br />  &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;<br />  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />&lt;filter-mapping&gt;<br />  &lt;filter-name&gt;Acegi HTTP BASIC Authorization Filter&lt;/filter-name&gt;<br />  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />&lt;filter-mapping&gt;<br />  &lt;filter-name&gt;Acegi Security System for Spring Auto Integration Filter&lt;/filter-name&gt;<br />  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />&lt;filter-mapping&gt;<br />  &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt;<br />  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br /></font><br />这里，需要注意以下两点：<br />1) 这几个filter的顺序是不能更改的，顺序不对将无法正常工作；<br />2) 如果你的应用不需要安全传输，如https，则将"Acegi Channel Processing Filter"相关内容注释掉即可；<br />3) 如果你的应用不需要Spring提供的远程访问机制，如Hessian and Burlap，将"Acegi HTTP BASIC Authorization <br />Filter"相关内容注释掉即可。<br /><br /><b><font color="#0000ff" size="3">[applicationContext.xml]</font></b><br />接下来就是要添加applicationContext.xml中的内容了，从刚才FilterToBeanFactory的解释可以看出，真正的filter都<br />在Spring的applicationContext中管理：<br /><br />1) 首先，你的数据库中必须具有保存用户名和密码的table，Acegi要求table的schema必须如下：<br /><br /><font color="#800080">CREATE TABLE users (<br />    username VARCHAR(50) NOT NULL PRIMARY KEY,<br />    password VARCHAR(50) NOT NULL,<br />    enabled BIT NOT NULL<br />);<br />CREATE TABLE authorities (<br />    username VARCHAR(50) NOT NULL,<br />    authority VARCHAR(50) NOT NULL<br />);<br />CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority );<br />ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users<br />(username);<br /></font><br />2) 添加访问你的数据库的datasource和Acegi的jdbcDao，如下：<br /><br /><font color="#800080">&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br />  &lt;property name="driverClassName"&gt;&lt;value&gt;${jdbc.driverClassName}&lt;/value&gt;&lt;/property&gt;<br />  &lt;property name="url"&gt;&lt;value&gt;${jdbc.url}&lt;/value&gt;&lt;/property&gt;<br />  &lt;property name="username"&gt;&lt;value&gt;${jdbc.username}&lt;/value&gt;&lt;/property&gt;<br />  &lt;property name="password"&gt;&lt;value&gt;${jdbc.password}&lt;/value&gt;&lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"&gt;<br />  &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt;<br />&lt;/bean&gt;</font><br /><br />3) 添加DaoAuthenticationProvider:<br /><br /><font color="#800080">&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;<br />  &lt;property name="authenticationDao"&gt;&lt;ref bean="authenticationDao"/&gt;&lt;/property&gt;<br />  &lt;property name="userCache"&gt;&lt;ref bean="userCache"/&gt;&lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"&gt;<br />  &lt;property name="minutesToIdle"&gt;&lt;value&gt;5&lt;/value&gt;&lt;/property&gt;<br />&lt;/bean&gt;</font><br /><br />如果你需要对密码加密，则在daoAuthenticationProvider中加入：&lt;property name="passwordEncoder"&gt;&lt;ref <br />bean="passwordEncoder"/&gt;&lt;/property&gt;，Acegi提供了几种加密方法，详细情况可看包<br />net.sf.acegisecurity.providers.encoding<br /><br />4) 添加authenticationManager:<br /><br /><font color="#800080">&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;<br />  &lt;property name="providers"&gt;<br />    &lt;list&gt;<br />      &lt;ref bean="daoAuthenticationProvider"/&gt;<br />    &lt;/list&gt;<br />   &lt;/property&gt;<br />&lt;/bean&gt;</font><br /><br />5) 添加accessDecisionManager:<br /><br /><font color="#800080">&lt;bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"&gt;<br />  &lt;property name="allowIfAllAbstainDecisions"&gt;<br />    &lt;value&gt;false&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="decisionVoters"&gt;<br />    &lt;list&gt;&lt;ref bean="roleVoter"/&gt;&lt;/list&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/&gt;<br /></font><br />6) 添加authenticationProcessingFilterEntryPoint:<br /><br /><font color="#800080">&lt;bean id="authenticationProcessingFilterEntryPoint" <br />class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;<br />  &lt;property name="loginFormUrl"&gt;&lt;value&gt;/acegilogin.jsp&lt;/value&gt;&lt;/property&gt;<br />  &lt;property name="forceHttps"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;<br />&lt;/bean&gt;</font><br /><br />其中acegilogin.jsp是登陆页面，一个最简单的登录页面如下：<br /><br /><font color="#800080">&lt;%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %&gt;<br />&lt;%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %&gt;<br />&lt;%@ page import="net.sf.acegisecurity.AuthenticationException" %&gt;<br />&lt;html&gt;<br />  &lt;head&gt;<br />    &lt;title&gt;Login&lt;/title&gt;<br />  &lt;/head&gt;<br /><br />  &lt;body&gt;<br />    &lt;h1&gt;Login&lt;/h1&gt;<br />    &lt;form action="&lt;c:url value='j_acegi_security_check'/&gt;" method="POST"&gt;<br />      &lt;table&gt;<br />        &lt;tr&gt;&lt;td&gt;User:&lt;/td&gt;&lt;td&gt;&lt;input type='text' name='j_username'&gt;&lt;/td&gt;&lt;/tr&gt;<br />        &lt;tr&gt;&lt;td&gt;Password:&lt;/td&gt;&lt;td&gt;&lt;input type='password' name='j_password'&gt;&lt;/td&gt;&lt;/tr&gt;<br />        &lt;tr&gt;&lt;td colspan='2'&gt;&lt;input name="submit" type="submit"&gt;&lt;/td&gt;&lt;/tr&gt;<br />        &lt;tr&gt;&lt;td colspan='2'&gt;&lt;input name="reset" type="reset"&gt;&lt;/td&gt;&lt;/tr&gt;<br />      &lt;/table&gt;<br />    &lt;/form&gt;<br />  &lt;/body&gt;<br />&lt;/html&gt;</font><br /><br />7) 添加filterInvocationInterceptor:<br /><br /><font color="#800080">&lt;bean id="filterInvocationInterceptor" <br />class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;<br />  &lt;property name="authenticationManager"&gt;<br />    &lt;ref bean="authenticationManager"/&gt;<br />  &lt;/property&gt;<br />  &lt;property name="accessDecisionManager"&gt;<br />    &lt;ref bean="accessDecisionManager"/&gt;<br />  &lt;/property&gt;<br />  &lt;property name="objectDefinitionSource"&gt;<br />    &lt;value&gt;<br />      CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<br />      \A/sec/administrator.*\Z=ROLE_SUPERVISOR<br />      \A/sec/user.*\Z=ROLE_TELLER<br />    &lt;/value&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;</font><br /><br />这里请注意，要objectDefinitionSource中定义哪些页面需要权限访问，需要根据自己的应用需求进行修改，我上面给出<br />的定义的意思是这样的：<br /> a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON意思是在比较请求路径时全部转换为小写<br /> b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR意思是只有权限为ROLE_SUPERVISOR才能访问/sec/administrator*的页面<br /> c. \A/sec/user.*\Z=ROLE_TELLER意思是只有权限为ROLE_TELLER的用户才能访问/sec/user*的页面<br /><br />8) 添加securityEnforcementFilter:<br /><br /><font color="#800080">&lt;bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"&gt;<br />  &lt;property name="filterSecurityInterceptor"&gt;<br />    &lt;ref bean="filterInvocationInterceptor"/&gt;<br />  &lt;/property&gt;<br />  &lt;property name="authenticationEntryPoint"&gt;<br />    &lt;ref bean="authenticationProcessingFilterEntryPoint"/&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br /><br /><font color="#000000">9) 添加authenticationProcessingFilter:</font><br /><br />&lt;bean id="authenticationProcessingFilter" <br />class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"&gt;<br />  &lt;property name="authenticationManager"&gt;<br />    &lt;ref bean="authenticationManager"/&gt;<br />  &lt;/property&gt;<br />  &lt;property name="authenticationFailureUrl"&gt;<br />    &lt;value&gt;/loginerror.jsp&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="defaultTargetUrl"&gt;<br />    &lt;value&gt;/&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="filterProcessesUrl"&gt;<br />    &lt;value&gt;/j_acegi_security_check&lt;/value&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;</font><br />其中authenticationFailureUrl是认证失败的页面。<br /><br />10) 如果需要一些页面通过安全通道的话，添加下面的配置:<br /><br /><font color="#800080">&lt;bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter"&gt;<br />  &lt;property name="channelDecisionManager"&gt;<br />    &lt;ref bean="channelDecisionManager"/&gt;<br />  &lt;/property&gt;<br />  &lt;property name="filterInvocationDefinitionSource"&gt;<br />    &lt;value&gt;<br />      CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<br />      \A/sec/administrator.*\Z=REQUIRES_SECURE_CHANNEL<br />      \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL<br />      \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL<br />      \A.*\Z=REQUIRES_INSECURE_CHANNEL<br />    &lt;/value&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl"&gt;<br />  &lt;property name="channelProcessors"&gt;<br />    &lt;list&gt;<br />      &lt;ref bean="secureChannelProcessor"/&gt;<br />      &lt;ref bean="insecureChannelProcessor"/&gt;<br />    &lt;/list&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/&gt;<br />&lt;bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/&gt;</font><br /><br /><b><font color="#0000ff" size="3">[缺少了什么？]</font></b><br />Acegi目前提供了两种"secure object"，分别对页面和方法进行安全认证管理，我这里介绍的只是利用<br />FilterSecurityInterceptor对访问页面的权限控制，除此之外，Acegi还提供了另外一个Interceptor——<br />MethodSecurityInterceptor，它结合runAsManager可实现对对象中的方法的权限控制，使用方法可参看Acegi自带的文档<br />和contact范例。<br /><br /><b><font color="#0000ff" size="3">[最后要说的]</font></b><br />本来以为只是说明如何使用Acegi而已，应该非常简单，但真正写起来才发现想要条理清楚的理顺所有需要的bean还是很<br />困难的，但愿我没有遗漏太多东西，如果我的文章有什么遗漏或错误的话，还请参看Acegi自带的quick-start范例，但请<br />注意，这个范例是不能直接拿来用的。</font>
						</font>
				</div>
		</div>
<img src ="http://www.blogjava.net/fisher/aggbug/92379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fisher/" target="_blank">Fisher</a> 2007-01-08 15:14 <a href="http://www.blogjava.net/fisher/articles/92379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring中ApplicationContext加载机制</title><link>http://www.blogjava.net/fisher/articles/90130.html</link><dc:creator>Fisher</dc:creator><author>Fisher</author><pubDate>Tue, 26 Dec 2006 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/fisher/articles/90130.html</guid><wfw:comment>http://www.blogjava.net/fisher/comments/90130.html</wfw:comment><comments>http://www.blogjava.net/fisher/articles/90130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fisher/comments/commentRss/90130.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fisher/services/trackbacks/90130.html</trackback:ping><description><![CDATA[
		<font color="#333333">Spring中ApplicationContext加载机制。 <br />    加载器目前有两种选择：ContextLoaderListener和ContextLoaderServlet。 <br />    这两者在功能上完全等同，只是一个是基于Servlet2.3版本中新引入的Listener接口实现，而另一个基于Servlet接口实现。开发中可根据目标Web容器的实际情况进行选择。 <br /><br /></font>
		<table width="672" border="0">
				<tbody>
						<tr>
								<td width="388">
										<font color="#333333">配置非常简单，在web.xml中增加： <br />&lt;listener&gt; <br />  &lt;listener-class&gt; <br />       org.springframework.web.context.ContextLoaderListener <br />  &lt;/listener-class&gt; <br />&lt;/listener&gt; <br />或： <br />&lt;servlet&gt; <br />    &lt;servlet-name&gt;context&lt;/servlet-name&gt; <br />    &lt;servlet-class&gt; <br />       org.springframework.web.context.ContextLoaderServlet <br />    &lt;/servlet-class&gt; <br />    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; <br />&lt;/servlet&gt; </font>
								</td>
								<td width="274">
								</td>
						</tr>
				</tbody>
		</table>
		<font color="#333333">
				<br />通过以上配置，Web容器会自动加载/WEB-INF/applicationContext.xml初始化 <br />ApplicationContext实例，如果需要指定配置文件位置，可通过context-param加以指定： <br />&lt;context-param&gt; <br />    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; <br />    &lt;param-value&gt;/WEB-INF/myApplicationContext.xml&lt;/param-value&gt; <br />&lt;/context-param&gt; <br /><br />配置完成之后，即可通过 <br /> WebApplicationContextUtils.getWebApplicationContext方法在Web应用中获取ApplicationContext引用。 <br /><br />如：ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(); <br />    LoginAction action=(LoginAction)ctx.getBean("action");<br /><br /><br /></font>转载：<a href="http://hi.baidu.com/jgs80/blog/item/307a40a794a7ad95d1435896.html">http://hi.baidu.com/jgs80/blog/item/307a40a794a7ad95d1435896.html</a><img src ="http://www.blogjava.net/fisher/aggbug/90130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fisher/" target="_blank">Fisher</a> 2006-12-26 15:48 <a href="http://www.blogjava.net/fisher/articles/90130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>