zoukankan      html  css  js  c++  java
  • Spring3之Security

    1.spring security介绍

      Spring Security原来叫做Acegi Security,可用于加强任何Java应用的安全,但是最常用于基于Web的应用。下面首先理解几个安全术语:

    验证:是验证一个角色与其声称的身份相符的过程。这个角色可以是一个用户、一个设备或者一个系统,但是最典型的是一个用户。角色必须提供身份证据进行验证。这个证据称作凭据,当目标角色是用户时通常是一个密码。

    授权:是向已验证的用户授予权限,使其能够访问目标应用的特定资源的过程。收全过程必须在验证过程之后进行。一般来说,权限按照角色授予。

    访问控制:意指控制对应应用资源的访问。访问控制必须作出用户是否允许访问某个资源的决策,这个决策称为访问控制决策。 通过比较资源的访问属性和用户被授予的权限或者其他特性作出。

     

    2.基本配置

    Spring Security的安全控制是通过 一系列的ServletRequest过滤器实现的。Spring Security提供配置DelegatingFilterProxy拦截包装所有的URL请求,委托给其他的过滤器,因此在web.xml中配置此过滤器,如下:

      <filter>

            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

     集成Web环境的通用配置,当然需配置加载所有的Bean的ContextLoadListener,或者其他配置方式。

    从基本配置可以看出Spring Security的主要依赖于这些代理和过滤器,来实现请求的安全控制。Spring Security在自动配置中建立了一些过滤器,这些过滤器都是按照链顺序组合的,servlet请求按照一定的顺序从一个过滤器到下一个穿过整个过滤器链,最终到达目标servlet,当然响应就倒过来传了。而S-Security拥有更多的过滤器,能根据请求改变控制行为。S-Security提供了相应的组件来进行认证,如AuthenticationManager接口来验证用户的凭证信息,Authentication接口获取用户的详细信息。在默认过滤链中,最后一个过滤器是FilterSecurityInterceptor,它的作用是判断请求是允许还是要拒绝。S-Security使用访问决策控制器组件来负责做出决策,如AccessDecisionManager接口,我们可以实现完全的自定义授权机制配置,如投票器和访问决策器的配置。

      

    3.url的安全

    S-Security通过简单的配置,以声明式的方法加强应用的URL访问安全,当然同样才用过滤器来处理。如果我们Web应用的安全需求是简单而典型,这可以将autoconfig属性设置为true,这样Spring Security就会自动注册和配置一些基本服务,如基于表单的登陆注销,匿名登录,HTTP基本验证,Remember-me等。其通过一个或者多个<intercept-url>元素限制对特定URL的访问,每个<intercept-url>元素指定一个URL模式,以及一个访问这些URL所需的访问属性。我们大都使用SpEL来实现这些访问属性的控制。如下配置:

        <http auto-config="true">

        <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
                <intercept-url pattern="/messagePost*" access="ROLE_USER" />
                <intercept-url pattern="/messageDelete" access="ROLE_ADMIN"  />
                <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> 
          </http>

      还可以在<authentication-provider>元素中配置验证服务,就在我们上述讲到的<authentication-manager>内,S-security支持很多验证方法,也可以自定义验证策略。

    4.web登录的安全

     安全的Web登陆在互联网上尤其重要,S-security支持多种用户登录Web应用的方法,有包含登陆表单的默认网页,匿名登录,remember-me登陆等。HTTP基本验证支持可以通过<http-basic>元素配置,如果基本验证和基于表单的登陆同时启用,将会使用后者。

    基于表单的登陆服务将显示一个包含登陆表单的网页,通过<form-login>元素来配置,默认情况下,S-security自动创建一个登陆页面并将其映射到URL /spring_security_login。如下: <a href="<c:url value="/spring_security_login" />" Log in </a>  ,当然如果我们自定义登陆页面需如有如下几部分大致如下:

     <form method="POST" action="<c:url value="/j_spring_security_check" />" >

    <table>
            <tr><td>Username</td>
                <td><input type="text" name="j_username"/></td>
            </tr>
            <tr><td>Password</td>
                <td><input type="password" name="j_password" /></td>
            </tr>
            <tr><td>Remember Me</td>
                <td><input type="checkbox" name="_spring_security_remember_me" /></td>
            </tr>
            <tr><td>
                <input type="submit" value="Login"/>
                <input type="reset" value="Reset" />
                </td></tr>
    </table></form>

     默认在成功登陆后进入项目根目录,如果想要重定向到别的目录可以在<form-login>中的default-target-url属性来配置,如果登陆失败可通过authentication-failure-url属性配置,想要知道发生了什么错误,可以通过访问会话范围内的SPRING_SECURITY_LAST_EXCEPTION来显示。

    注销服务通过<logout>配置,默认映射到URL /j_spring_security_logout,与login类似的配置。此外匿名登录通过在<http>内的<anonymous/>配置,Remember-me通过<remember-me/>配置,静态的remember-me可能导致安全问题,因此可以存储到数据库使用滚动令牌。

    5.验证用户

      S-security支持多种验证方法,包括这些方法的内建提供者实现,大部分常见的额验证提供者利用存储用户细节的用户存储库,如内存、关系数据库、LDAP存储库等验证用户。存储时务必要使用密文存储,通常使用单向散列函数(如MD5和SHA)进行编码,Spring提供了这些算法的内建密码编码器。

    如果应用中有少数用户,并且很少修改用户细节,可以考虑直接配在配置文件中加载到内存中认证,在<user-service>中定义用户细节,也可以写到属性文件中去。

    较多的我们还是将用户细节存储到数据库中,这样更容易维护。同样我们要建立相应的表和列,并在,<authentication-provider>中加入<jdbc-user-service>配置,用来查询数据库获得用户细节。但是我们自己的用户表,不可能和它完全一致,spring支持用自定义的SQL语句查询用users-by-username-query和authorities-by-username-query属性自定查询和授权语句。既然密码需要用密文来存放,则我们需要自己指定使用的加密算法。通过配置<password-encode>来指定,然后在<user-service>中的用户密码属性,提供该算法加密后的密文形式,或者在数据库中存放密文。

    对于企业来讲用户的细节也用可能存放在LDAP信息库中,因此S-security也支持访问LDAP验证用户,同样我们配置一个<ldap-user-service>标签,定义从LDAP中搜索用户的方法,大部分情况下我们需要指定加密的算法,这个和LDAP中的一致。实例如下:

     <password-encoder hash="{sha}"/>

         <ldap-user-service server-ref="ldapServer" 
                user-search-filter
    ="uid={0}" user-search-base="ou=people"
                group-search-filter
    ="member={0}" group-search-base="ou=groups"/>

      如果数据库或者LDAP是远程的,则对请求的响应会有影响,S-security提供了缓存服务的缓存实现。直接加上一个cache-ref属性就可以了。

    6.访问控制策略

      ACL(access control list),当一个用户视图访问应用中的资源时,应用必须根据acl决定哪些资源可以访问,哪些不可访问。在S-security中,访问控制决策由访问决策管理器作出,决策管理器必须实现AccessDecisionManager接口,可随意实现这个接口创建访问决策管理器,当时S-security自带3种基于投票的访问决策管理器:

    AffirmativeBased: 至少一个投票者投票赞成授予权限

    ConsensusBased: 投票者一致赞成授予权限

    UnanimousBased: 所有投票者赞成或者弃权(没有拒绝访问的投票者) 

    每个投票者都必须实现AccessDecisionVoter接口,投票者可以投票赞成授权、弃权访问资源。投票的结果由AccessDecisionVoter接口中定义的ACCESS_GRANTED,ACCESS_DENIED和ACCESS_ABSTAIN常量表示。S-security自动配置一个AffirmativeBased访问决策控制器,配置如下两个投票者:

    RoleVoter:根据用户角色对访问控制决策投票。它只处理以ROLE_前缀开始的访问属性,但是这个前缀可以定制。如果没有这样的访问属性,它会弃权。

    AuthenticatedVoter:根据用户验证级别对访问控制决策投票。它只处理IS_AUTHENTICATED_FULLY,IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_ANONYMOUSLY访问属性。如果用户的验证级别高于所需的属性则投票授权。

     如果自定义投票者需要实现AccessDecisionVoter接口,自定义属性前缀,没有这样前缀的访问属性则会投弃权票。接下来我们就需要把这个自定义的投票者和系统默认的两个投票者配置在一起,包含在AffirmativeBased下,或者其他决策管理器下。 

    7.方法调用的安全 

      S-security还可以让你在服务层的方法调用上安全控制,你可以实现方法上的细粒度的控制,通过在Bean中其纳入一个<security:intercept-methods>元素来实现,也可配置全局的<global-method-security>元素,加强与AspectJ切入点表达式匹配的多个方法的安全。还可通过加上@Secured注解,然后在<global-method-security>中启用他们。如下:

    <bean id="xyzService" class="xx.yy.zz.xyzService">

                <security:intercept-methods access-decision-manager-ref="accessDecisionManager">
                        <security:protect method="xx.yy.zz.xyzService.xyz" access="ROLE_ADMIN,ROLE_USER"/>
                </security:intercept-methods>

         </bean> 

    还可在<global-method-security>中定义全局切入点,使用AspectJ切入点表达式加强方法安全,如:

    <global-method-security access-decision-manager-ref="accessDecisionManager">

            <protect-pointcut expression="execution( * xx.yy.zz.*Service.xyz*(..))" access="ROLE_ADMIN,ROLE_USER"/>

         </global-method-security> 

      还可使用注解的形式,在方法的前加上@Secured注解,并且可以用注解值指定访问属性,类型为String[],如:

    @Secured({"ROLE_ADMIN","ROLE_USER"}) 

    public void xyz(){....} 

    当然这种方法需要在配置中启用注解,如下:

    <global-method-security secured-annotations="enabled" access-decision-manager-ref="accessDecisionManager"> 

    8.视图控制的安全

      在Web应用中,有时候我们想控制具有不同权限的用户的显示视图,S-security也提供了该服务的支持。S-security有一个jsp的标签库,用于处理Jsp视图中的安全控制。使用时首先将标签库引入  <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

    <security:authentication>标记暴露当前用户的Authentication对象,供你显示其属性。通过<security:authorize>与SpEL的配合有条件显示不同内容,如:

    <security:authorize ifAllGranted="ROLE_ADMIN,ROLE_USER">

            <tr><td>Author</td><td>${message.author}</td></tr>

         </security:authorize> 

       

    9.领域对象的安全(ACL)

      有时候如果更加复杂的安全需求,需要在不同对象上进行安全控制,S-security也提供了该服务的支持。Spring提供ACL包含一个与领域对象关联的对象标识,同时保存多个访问控制项。其含有两个核心部分:

    权限:ACE的权限由一个特别的位屏蔽代表,每位的值用于特定类型的权限,BasePermission预先定义了5中基本权限的常量值READ(0)、WRITE(1)、CREATE(2)、DELETE(3)、ADMINISTRATION(4),括号里代表位。

    安全标识:每个ACE包含特定的SID的权限,其可以是一个与权限关联的角色或者授权。

    S-security还定义了用于读取和维护模型的API,并为这些API提供了高性能的JDBC实现。在S-security中有两个定义ACL服务操作的接口,AclService和MutableAclService,后面是前者的子接口,定义用于创建、更新和删除Acl操作。配置如下:

     <bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">

                <constructor-arg ref="dataSource" />
                <constructor-arg ref="lookupStrategy"/>
                <constructor-arg ref="aclCache"/>
                <property name="sidIdentityQuery" value="values identity_val_local()"/>
         </bean>

      第二个参数sidIdentityQuery是进行ACL服务查找的策略。S-security自带的唯一实现是BasicLookupStrategy,它使用标准和兼容的SQL语句进行基本查找。如果需要其他的查找性能,可以实现LookupStrategy接口创建自己的查找策略。

    在我们的Service和Dao中,可以用上述的Acl服务,为对象维护acl。如下所示:

     ...

    ObjectIdentity oid = new ObjectIdentityImpl(Message.class,message.getId());
    MutableAcl acl = mutableAclService.createAcl(oid);
    acl.insertAce(0,BasePermission.ADMINISTRATION,new PrincipalSid(message.getAuthor()),true);
    acl.insertAce(1,BasePermission.DELETE,new GrantedAuthoritySid("ROLE_ADMIN"),true);
    acl.insertAce(2,BasePermission.READ,new GrantedAuthoritySid("ROLE_USER"),true);
    mutableAclService.updateAcl(acl);
         ...

      上述的定义则是允许message的作者管理;允许具有ADMIN角色的用户删除它;允许USER角色的用户阅读它。

    我们已经可将aclService定义好了,并且已经注入进Spring相关的Service层Bean中。下面我们便可以根据ACL控制涉及该对象方法的安全控制了。S-security自己提供了acl投票者类 AclEntryVoter类,同时也允许自定义基于ACL的投票者。AclEntryVoter使用时需指定processDomainObjectClass属性,就是指明我们对哪个类的对象添加了ACL服务。该投票者类不可为基于http的访问决策投票,即我们不能直接将其包含在全局访问决策管理器中。但可使用如下方式:

    <global-method-security secured-annotation="enabled" access-decision-manager-ref="aclAccessDecisionManager"/>

    同样S-security也支持tag的方式,有条件显示相应的视图,配合使用 <security:accesscontrollist>标签和SpEL。

     如果用户调用了方法等返回了对象,我们也要进行ACL控制的话。可使用AclEntryAfterInvocationProvider和AclEntryAfterInvocationCollectionFilteringProvider实例,前者如果不具有权限会抛出异常阻止返回,后者会进行过滤结果。在Bean的配置中嵌入<customafter-invocation-provider>元素,就能在S-security中注册一个自定义后调用提供者。

  • 相关阅读:
    Saltstack module acl 详解
    Saltstack python client
    Saltstack简单使用
    P5488 差分与前缀和 NTT Lucas定理 多项式
    CF613D Kingdom and its Cities 虚树 树形dp 贪心
    7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
    luogu P5633 最小度限制生成树 wqs二分
    7.1 NOI模拟赛 dp floyd
    springboot和springcloud
    springboot集成mybatis
  • 原文地址:https://www.cnblogs.com/kingcucumber/p/2888621.html
Copyright © 2011-2022 走看看