无极,无际,无迹

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  3 Posts :: 8 Stories :: 10 Comments :: 0 Trackbacks
接着来。
2.过滤器的配置:
  我们已经配置了那些过滤器了,但是要跟spring context中的对象对应,于是乎,做了如下配置:
  <beans:bean id="securityContextPersistenceFilter"
          class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
  </beans:bean>
  <beans:bean id="logoutFilter"
          class="org.springframework.security.web.authentication.logout.LogoutFilter" >
          <beans:constructor-arg type="java.lang.String" value="/"/>
          <beans:constructor-arg ref="securityContextLogoutHandler"/>
  </beans:bean>
  <beans:bean id="basicAuthenticationFilter"
          class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
          <beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
          <beans:property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"></beans:property>
  </beans:bean>
  <beans:bean id="requestCacheAwareFilter"
          class="org.springframework.security.web.savedrequest.RequestCacheAwareFilter">
  </beans:bean>
  <beans:bean id="securityContextHolderAwareRequestFilter"
          class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter">
  </beans:bean>
  <beans:bean id="anonymousAuthenticationFilter"
          class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
          <beans:property name="userAttribute" ref="anonymousUserAttribute"></beans:property>
          <beans:property name="key"      value="anonymousUser"/>
  </beans:bean>
  <beans:bean id="sessionManagementFilter"
          class="org.springframework.security.web.session.SessionManagementFilter">
          <beans:constructor-arg  type="org.springframework.security.web.context.SecurityContextRepository" ref="sessionSecurityContextRepository"/>
  </beans:bean>
  <beans:bean id="exceptionTranslationFilter"
          class="org.springframework.security.web.access.ExceptionTranslationFilter">
          <beans:property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"/>
  </beans:bean>
  <beans:bean id="filterSecurityInterceptor"
          class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
          <beans:property name="authenticationManager"  ref="authenticationManager" />
          <beans:property name="accessDecisionManager"  ref="accessDecisionManager" />
          <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
  </beans:bean>
 
  <!-- The following beans are configured for the filters upstairs -->
  <!-- ///////////////////////////////////////// -->
  <!-- ////for LogoutFilter///////////////////// -->
  <!-- ///////////////////////////////////////// -->
  <beans:bean id="securityContextLogoutHandler"
          class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
  </beans:bean>
  <!-- ///////////////////////////////////////// -->
  <!-- ////for AnonymousAuthenticationFilter//// -->
  <!-- ///////////////////////////////////////// -->
  <beans:bean id="anonymousUserAttribute"
          class="org.springframework.security.core.userdetails.memory.UserAttribute">
          <beans:property name="authorities">
            <beans:list>
               <beans:ref  bean="anonymousUserGrantedAuthority" />
            </beans:list>
          </beans:property>
          <beans:property name="password" value="anonymousUser"/>
  </beans:bean>
  <beans:bean id="anonymousUserGrantedAuthority"
          class="org.springframework.security.core.authority.GrantedAuthorityImpl">
          <beans:constructor-arg type="java.lang.String" value="ROLE_ANONYMOUS"/>
  </beans:bean>
  <!-- ///////////////////////////////////////// -->
  <!-- ////for SessionManagementFilter////////// -->
  <!-- ///////////////////////////////////////// -->
  <beans:bean id="sessionSecurityContextRepository"
          class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
  </beans:bean>
  <!-- ///////////////////////////////////////// -->
  <!-- ////for FilterSecurityInterceptor//////// -->
  <!-- ///////////////////////////////////////// -->
  <beans:bean id="accessDecisionManager"
          class="org.springframework.security.access.vote.AffirmativeBased">
          <beans:property name="decisionVoters">
            <beans:list>
               <beans:ref bean="webExpressionVoter"/>
            </beans:list>
          </beans:property>
  </beans:bean>
  <beans:bean id="webExpressionVoter"
          class="com.saveworld.authentication.web.access.expression.MyWebExpressionVoter">
  </beans:bean>
  <beans:bean id="securityMetadataSource"
          class="com.saveworld.authentication.web.access.intercept.MyFilterInvocationSecurityMetadataSource">
          <beans:constructor-arg type="org.springframework.security.web.util.UrlMatcher" ref="urlMatcher" />
          <beans:constructor-arg type="javax.sql.DataSource" ref="proxoolDataSource" />
          <beans:constructor-arg type="org.springframework.security.web.access.expression.WebSecurityExpressionHandler"
                                     ref="expressionHandler" />
  </beans:bean>
  <beans:bean id="urlMatcher"
          class="org.springframework.security.web.util.AntUrlPathMatcher" >
          <beans:constructor-arg type="boolean" value="true" />
  </beans:bean>
  <beans:bean id="expressionHandler"
          class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
  </beans:bean>
这里做几点说明:
   (1) 数据库中的权限相关的表:
            ROLES
            AUTHORITIES
            USER_AUTHS
            ROLE_AUTHS
            USERS
       这里的表结构还不是最终的,所以就不发上来误导兄弟姐妹们了。
       关键是看我们如何加载这些持久化的东西。
       这个就要看看filterSecurityInterceptor了,它里面使用了一个securityMetadataSource,本地的securityMetadataSource实现代码:
      public class MyFilterInvocationSecurityMetadataSource extends DefaultFilterInvocationSecurityMetadataSource{
    private final static Log logger = LogFactory.getLog(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
    private DataSource datasource;
   
    public MyFilterInvocationSecurityMetadataSource(UrlMatcher urlMatcher,
                                                    DataSource datasource,
                                                    WebSecurityExpressionHandler expressionHandler) {
        super(urlMatcher, processMap(initializeFromDb(datasource,null),expressionHandler.getExpressionParser()));
    }

    //This method is usefulless for now!
    //Because this method is used for parsing the expression kind
    private static LinkedHashMap<RequestKey, Collection<ConfigAttribute>> processMap(
            LinkedHashMap<RequestKey,Collection<ConfigAttribute>> requestMap, ExpressionParser parser) {
        Assert.notNull(parser, "SecurityExpressionHandler returned a null parser object");

        LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestToExpressionAttributesMap =
            new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>(requestMap);

        for (Map.Entry<RequestKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
            RequestKey request = entry.getKey();
            Assert.isTrue(entry.getValue().size() == 1, "Expected a single expression attribute for " + request);
            ArrayList<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(1);
            String expression = entry.getValue().toArray(new ConfigAttribute[1])[0].getAttribute();
            logger.debug("Adding web access control expression '" + expression + "', for " + request);
            try {
                //Replacing WebExpressionConfigAttribute with MyWebExpressionConfigAttribute
                //which is defined locally!
                attributes.add(new MyWebExpressionConfigAttribute(parser.parseExpression(expression)));
            } catch (ParseException e) {
                throw new IllegalArgumentException("Failed to parse expression '" + expression + "'");
            }

            requestToExpressionAttributesMap.put(request, attributes);
        }

        return requestToExpressionAttributesMap;
    }

    private static LinkedHashMap<RequestKey,Collection<ConfigAttribute>> initializeFromDb(DataSource datasource,LinkedHashMap<RequestKey, Collection<ConfigAttribute>> configMap){
        LinkedHashMap<RequestKey,Collection<ConfigAttribute>> result =
            new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();
        Connection conn = null;
        Statement  stmt = null;
        ResultSet  rs   = null;
        try {
            conn = datasource.getConnection();
            stmt = conn.createStatement();
            StringBuilder sql = new StringBuilder("SELECT b.AUTHORITYPATTERN ,'hasRole('||chr(39)||a.ROLENAME||chr(39)||')' rolename ")
                                             .append(" FROM ROLES a,AUTHORITIES b,ROLE_AUTHS c ")
                                             .append(" WHERE a.rolename = c.rolename AND b.authorityname = c.authorityname");
           
            rs = stmt.executeQuery(sql.toString());
            String roles = "";
            RequestKey key = null;
            List<ConfigAttribute> value = null;
            while(rs != null && rs.next()){
                key = new RequestKey(rs.getString(1));
                roles = rs.getString(2);
                String[] roleArray = roles.split(",|\\s+|;");
                value = new ArrayList<ConfigAttribute>();
                for(String role : roleArray){
                    ConfigAttribute config = new SecurityConfig(role);
                    value.add(config);
                }
                result.put(key, value);
            }
            //just for test
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            try{
                rs.close();
                stmt.close();
                conn.close();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
        return result;
    }
   
   
   
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    public DataSource getDatasource() {
        return datasource;
    }

    public void setDatasource(DataSource datasource) {
        this.datasource = datasource;
    }
}
 (2) expressionHandler:
     这个东西要单独说说,我这里用的是表达式来检测用户角色的,所以,我用org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler来处理了,还有其他的方式,就是直接用角色进行判断,那样会更好,这里就不描述了!


posted on 2010-01-25 16:29 taochen 阅读(2294) 评论(4)  编辑  收藏 所属分类: java设计模式软件架构

Feedback

# re: SpringSecurity使用记录(六)-- 本地配置二 2010-07-12 11:46 kcai678
楼主,
能否将“com.saveworld.authentication.web.access.expression.MyWebExpressionVoter”的代码贴出来参考参考,谢谢。

  回复  更多评论
  

# re: SpringSecurity使用记录(六)-- 本地配置二 2010-09-09 17:30 taochen1984
@kcai678
好久没看邮件了,还望谅解

不过我的这个类没有多少特别之处,就是把那个WebExpressionVoter类转换成我的类了
然后在配置文件中配置了一下  回复  更多评论
  

# re: SpringSecurity使用记录(六)-- 本地配置二 2010-09-09 17:35 taochen1984
@kcai678
package com.saveworld.authentication.web.access.expression;

import java.util.Collection;

import org.springframework.expression.EvaluationContext;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.access.expression.WebSecurityExpressionHandler;


public class MyWebExpressionVoter implements AccessDecisionVoter {

private WebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();

public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
assert authentication != null;
assert object != null;
assert attributes != null;

MyWebExpressionConfigAttribute weca = findConfigAttribute(attributes);

if (weca == null) {
return ACCESS_ABSTAIN;
}

FilterInvocation fi = (FilterInvocation)object;
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, fi);

return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ?
ACCESS_GRANTED : ACCESS_DENIED;
}

private MyWebExpressionConfigAttribute findConfigAttribute(Collection<ConfigAttribute> attributes) {
for (ConfigAttribute attribute : attributes) {
if (attribute instanceof MyWebExpressionConfigAttribute) {
return (MyWebExpressionConfigAttribute)attribute;
}
}
return null;
}

public boolean supports(ConfigAttribute attribute) {
return attribute instanceof MyWebExpressionConfigAttribute;
}

public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(FilterInvocation.class);
}

public void setExpressionHandler(WebSecurityExpressionHandler expressionHandler) {
this.expressionHandler = expressionHandler;
}

}
  回复  更多评论
  

# re: SpringSecurity使用记录(六)-- 本地配置二 2012-05-17 11:11 cgh
@taochen1984
好像还涉及到MyWebExpressionConfigAttribute,麻烦您发下源码吧,谢啦。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: