spring security官网实例解析

今天因项目需要研究了下security,先下的官网的简单实例,自己分析了下,发上来给大家分享下。

贴图如下:

spring security官网实例解析

首先分析的是web.xml

代码如下:

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
    /WEB-INF/applicationContext-acegi-security.xml
   </param-value>
</context-param>

这个的作用是:contextConfigLocation 参数定义了要装入的 Spring 配置文件;

<filter>
        <filter-name>Acegi Filter Chain Proxy</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>

这个的作用是:按文档说法

org.springframework.security.util.FilterToBeanProxy的作用是提供一种特殊的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy来完成过滤功能,这好处是简化了web.xml的配置,并且充分利用了Spring IOC的优势。

org.acegisecurity.util.FilterChainProxy的作用是包含了处理认证过程的filter列表,每个filter都有各自的功能。

<filter-mapping>
      <filter-name>Acegi Filter Chain Proxy</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

这个的作用是对所用的请求进行过滤,进行权限控制。

<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

这个的作用是发布HttpSessionApplicationEvents和HttpSessionDestroyedEvent事件给spring的applicationcontext。

现在再看下applicationContext-acegi-security.xml。

<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
   <property name="filterInvocationDefinitionSource">
    <value><![CDATA[
     CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
     PATTERN_TYPE_APACHE_ANT
     /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
    ]]></value>
   </property>
</bean>

CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 定义URL在匹配之前必须先转为小写,PATTERN_TYPE_APACHE_ANT 定义了使用Apache ant的匹配模式,/**定义的将等号后面的过滤器应用在那些URL上,这里使用全部URL过滤,每个过滤器之间都适用逗号分隔,它们按照一定的顺序排列。

<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>

httpSessionContextIntegrationFilter是集成过滤器的一个实现,在用户的一个请求过程中,用户的认证信息通过SecurityContextHolder(使用ThreadLoacl实现)进行传递的,所有的过滤器都是通过SecurityContextHolder来获取用户的认证信息,从而在一次请求中所有过滤器都能共享Authentication(认证),减少了HttpRequest参数的传送,但是,ThreadLoacl不能跨越多个请求存在,所以,集成过滤器在请求开始时从Http会话中取出用户认证信息并创建一个SecurityContextHolder将Authentication对象保存在其中,在请求结束之后,在从SecurityContextHolder中获取Authentication对象并将其放回Http会话中,共下次请求使用,从而达到了跨越多个请求的目的。此过滤器必须在所有过滤器前使用。

<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
   <constructor-arg value="/index.jsp"/> <!-- 退出时指向的路径,此处为index.jsp-->
   <constructor-arg>
    <list>
     <ref bean="rememberMeServices"/>
     <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
    </list>
   </constructor-arg>
</bean>

此过滤器是退出过滤器。即进行退出登陆操作。 LogoutFilter的构造函数需要两个参数,第一个是退出系统后系统跳转到的URL,第二个是一个LogoutHandler类型的数组,这个数组里的对象都实现了LogoutHandler接口,并实现了它的logout方法,用户在发送退出请求后,会一次执行LogoutHandler数组的对象并调用它们的 logout方法进行一些后续的清理操作,主要是从SecurityContextHolder对象中清楚所有用户的认证信息(Authentication对象),将用户的会话对象设为无效,这些都时由SecurityContextLogoutHandler来完成。LogoutFilter还会清除Cookie记录,它由另外一个Bean来完成(RememberMeServices)。TokenBasedRememberMeServices继承自系统的AbstractRememberMeServices抽象类(实现了RememberMeServices和 LogoutHandler两个接口), RememberMeServices接口的loginSuccess方法负责在用户成功登录之后将用户的认证信息存入Cookie中,这个类在后续的过滤器执行过程中也会被用到。

<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
   <property name="authenticationManager" ref="authenticationManager"/>
   <property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>
   <property name="defaultTargetUrl" value="/"/>
   <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
   <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

authenticationProcessingFilter(认证过程过滤器),我们使用它来处理表单认证,当接受到与filterProcessesUrl所定义相同的请求时它开始工作。

下面列出了认证过程过滤器配置中各个属性的功能:

    1.authenticationManager     认证管理器

    2.authenticationFailureUrl 定义登录失败时转向的页面

    3.defaultTargetUrl         定义登录成功时转向的页面

    4.filterProcessesUrl        定义登录请求的地址(在web.xml中配置过)

    5.rememberMeServices        在验证成功后添加cookie信息

这里也用到了rememberMeServices,如果用户认证成功,将调用RememberMeServices的loginSuccess方法将用户认证信息写入Cookie中,这里也可以看到使用IoC的好处。

    决定用户是否有权限访问受保护资源的第一步就是要确定用户的身份,最常用的方式就是用户提供一个用户名和密码以确认用户的身份是否合法,这一步就是由认证过程过滤器调用authenticationManager(认证管理器)来完成的。org.springframework.security.AuthenticationManager接口定义了一个authenticate方法,它使用Authentication作为入口参数(只包含用户名和密码),并在验证成功后返回一个完整的Authentication对象(包含用户的权限信息GrantedAuthority数组对象),authenticationProcessingFilter(认证过程过滤器)会将这个完整的Authentication对象存入SecurityContext中,如果认证失败会抛出一个AuthenticationException并跳转到authenticationFailureUrl 定义的URL.

<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>

该Filter 负责通过Decorate Model(装饰模式),装饰的HttpServletRequest对象.其Wapper是ServletRequest包装类 HttpServletRequestWrapper的子类(SavedRequestAwareWrapper或者 SecurityContextHolderAwareRequestWrapper)。

<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
   <property name="authenticationManager" ref="authenticationManager"/>
   <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

RememberMeProcessingFilter的作用是它负责对所有HTTP请求进行拦截,当发现SecurityContextHolder中没有包含有效的Authentication对象时,自动调用RememberMeServices#autoLogin()方法从Cookie中获取用户名/密码的编码串进行自动登录。

<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
   <property name="key" value="changeThis"/>
   <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>

AnonymousProcessingFilter的作用是在匿名的时候(这时候是没有认证信息的)给这个用户分配一个匿名的认证信息。

<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
   <property name="authenticationEntryPoint">
    <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
     <property name="loginFormUrl" value="/acegilogin.jsp"/>
     <property name="forceHttps" value="false"/>
    </bean>
   </property>
   <property name="accessDeniedHandler">
    <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
     <property name="errorPage" value="/accessDenied.jsp"/>
    </bean>
   </property>
</bean>

ExceptionTranslationFilter是一个Spring Security过滤器,用来检测是否抛出了Spring Security异常。 这些异常会被AbstractSecurityInterceptor抛出,它主要用来提供验证服务。

accessDeniedHandler用于处理AccessDeniedException异常,当用户没有权限访问当前请求的资源时抛出此异常,并跳转自这里配置的/accessDenied.jsp页面。

authenticationEntryPoint(认证入口点),这里定义了用户登录的页面。

<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
   <property name="authenticationManager" ref="authenticationManager"/>
   <property name="accessDecisionManager">
    <bean class="org.acegisecurity.vote.AffirmativeBased">
     <property name="allowIfAllAbstainDecisions" value="false"/>
     <property name="decisionVoters">
      <list>
       <bean class="org.acegisecurity.vote.RoleVoter"/>
       <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
      </list>
     </property>
    </bean>
   </property>
   <property name="objectDefinitionSource">
    <value><![CDATA[
     CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
     PATTERN_TYPE_APACHE_ANT
     /secure/extreme/**=ROLE_SUPERVISOR
     /secure/**=IS_AUTHENTICATED_REMEMBERED
     /**=IS_AUTHENTICATED_ANONYMOUSLY
    ]]></value>
   </property>
</bean>

filterSecurityInterceptor(过滤器安全拦截器),该过滤器首先调用认证管理器来判断用户是否已被成功验证,如果没有被验证则重定向到登录界面。否则,从Authentication获取用户的权限信息,然后从objectDefinitionSource中获取URL所对应的权限,最后调用accessDecisionManager(访问决策管理器)来判断用户当前拥有的权限是否与当前受保护的URL资源对应的权限匹配,如果匹配就可以访问该URL资源,否则将抛出AccessDeniedException异常并返回客户端浏览器一个403错误(如果用户定义了accessDenied页面则会被重定向到该页,见:异常处理过滤器exceptionTranslationFilter中配置的accessDeniedHandler Bean)。从配置可以看出来,过滤器安全拦截器用到了我们前面配置的认证管理器,过滤器安全拦截器使用authenticationManager并调用它的providers(提供者列表)来对用户的身份进行验证并获取用户拥有的权限。如果用户被成功认证,过滤器安全拦截器将会使用accessDecisionManager(访问决策管理器)来判断已认证的用户是否有权限访问受保护的资源,这些受保护的资源由objectDefinitionSource属性定义。

<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
   <property name="userDetailsService" ref="userDetailsService"/>
   <property name="key" value="changeThis"/>
</bean>

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
   <property name="providers">
    <list>
     <ref local="daoAuthenticationProvider"/>
     <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
      <property name="key" value="changeThis"/>
     </bean>
     <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
      <property name="key" value="changeThis"/>
     </bean>
    </list>
   </property>
</bean>

Authentication对象才是Spring Security使用的进行安全访问控制用户信息安全对象。实际上,Authentication对象有未认证和已认证两种状态,在作为参数传入认证管理器(AuthenticationManager)的authenticate方法时,是一个未认证的对象,它从客户端获取用户的身份信息(如用户名,密码),可以是从一个登录页面,也可以从Cookie中获取,并由系统自动构造成一个Authentication对象。而这里提到的UserDetails代表一个用户安全信息的源(从数据库,LDAP服务器,CA中心返回),Spring Security要做的就是将这个未认证的Authentication对象和UserDetails进行匹配,成功后将UserDetails中的用户权限信息拷贝到Authentication中组成一个完整的Authentication对象,共其它组件共享。

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
   <property name="userDetailsService" ref="userDetailsService"/>
</bean>

DaoAuthenticationProvider,它可以从数据库中读取用户信息,同样也可以从一个用户属性文件中读取。

<!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
   <property name="userProperties">
    <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
     <property name="location" value="/WEB-INF/users.properties"/>
    </bean>
   </property>
</bean>

InMemoryDaoImpl类是UserDetailsService接口的一个实现,它从属性文件里读取用户信息,Spring Security使用一个属性编辑器将用户信息为我们组织成一个org.springframework.security.userdetails.memory.UserMap类的对象,我们也可以直接为它提供一个用户权限信息的列表,详见applicationContext-security.xml配置文件。

<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>

日记

转至http://www.baidu.com/s?wd=spring%20security实例&ie=utf-8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值