首页 > 其他 > 详细

acegi security实践教程—basic认证之debug调试

时间:2014-02-24 19:37:52      阅读:432      评论:0      收藏:0      [点我收藏+]
debug调试:
 运行:http://localhost:8080/acegitest1/index.jsp
 因为web.xml中配置:
      <filter-name >AcegiFilterChainProxy </filter-name >
         <filter-class >
            org.acegisecurity.util.FilterToBeanProxy
         </filter-class >
       <init-param >
      <param-name >targetBean </param-name >
      <param-value >filterChainProxy </param-value >
      </init-param >
  
1. 进入:FilterToBeanProxy代理类中的doFilter,因为init只执行一次,启动时已经执行一次,所以访问url时,直接直接进入doFilter方法。
  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        if (!initialized ) {
            doInit();
        }
        delegate.doFilter(request, response, chain);
    }
2. 进入:目标类filterChainProxy 中的doFilter
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        FilterInvocation fi = new FilterInvocation(request, response, chain);

        ConfigAttributeDefinition cad = this.filterInvocationDefinitionSource .getAttributes(fi);

        if (cad == null) {
            if ( logger.isDebugEnabled()) {
                logger.debug(fi.getRequestUrl() + " has no matching filters");
            }
            chain.doFilter(request, response);
            return;
        }
        Filter[] filters = obtainAllDefinedFilters(cad);
        if (filters.length == 0) {
            if ( logger.isDebugEnabled()) {
                logger.debug(fi.getRequestUrl() + " has an empty filter list");
            }

            chain.doFilter(request, response);
            return;
        }
        VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters);
        virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());
    }
   这个方法,主要获取aceg配置文件中,用户配置了多少个filter,并且filter顺序以数组形式展示,这样就开始filter过滤连了。
3.进入:过滤连第一个filter,也就是咱们配置的basicProcessingFilter,其中doFilter如下:
 
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        if (!(request instanceof HttpServletRequest)) {
            throw new ServletException( "Can only process HttpServletRequest");
        }

        if (!(response instanceof HttpServletResponse)) {
            throw new ServletException( "Can only process HttpServletResponse");
        }

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String header = httpRequest.getHeader( "Authorization");

        if (logger.isDebugEnabled()) {
            logger.debug( "Authorization header: " + header);
        }

        if ((header != null) && header.startsWith( "Basic ")) {
            String base64Token = header.substring(6);
            String token = new String(Base64.decodeBase64(base64Token.getBytes()));

            String username = "";
            String password = "";
            int delim = token.indexOf( ":");

            if (delim != -1) {
                username = token.substring(0, delim);
                password = token.substring(delim + 1);
            }

            if (authenticationIsRequired(username)) {
                UsernamePasswordAuthenticationToken authRequest =
                        new UsernamePasswordAuthenticationToken(username, password);
                authRequest.setDetails(authenticationDetailsSource .buildDetails((HttpServletRequest) request));

                Authentication authResult;

                try {
                    authResult = authenticationManager.authenticate(authRequest);
                } catch (AuthenticationException failed) {
                    // Authentication failed
                    if ( logger.isDebugEnabled()) {
                        logger.debug( "Authentication request for user: " + username + " failed: " + failed.toString());
                    }

                    SecurityContextHolder.getContext().setAuthentication( null);

                    if ( rememberMeServices != null) {
                        rememberMeServices.loginFail(httpRequest, httpResponse);
                    }

                    if ( ignoreFailure) {
                        chain.doFilter(request, response);
                    } else {
                        authenticationEntryPoint.commence(request, response, failed);
                    }

                    return;
                }

                // Authentication success
                if ( logger.isDebugEnabled()) {
                    logger.debug( "Authentication success: " + authResult.toString());
                }

                SecurityContextHolder.getContext().setAuthentication(authResult);

                if ( rememberMeServices != null) {
                    rememberMeServices.loginSuccess(httpRequest, httpResponse, authResult);
                }
            }
        }

        chain.doFilter(request, response);
    }
   这个关键在于if ((header != null) && header.startsWith( "Basic ")),其中basic认证是把用户输入用户名和密码存放到header中,basic认证的。因为这个header为null【稍后在分析header】,所以执行下一个filter。
4.进入exceptionfilter
5.进入filterInvocationInterceptor
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        invoke(fi);
    }
    跟着进去invoke,然后进入InterceptorStatusToken token = super.beforeInvocation(fi);最后关键处在于ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource ().getAttributes(object);
   obtainObjectDefinitionSource 大家眼熟吧,就是acegi配置文件,配置那个文件有那个角色。因为index.jsp没有配置,所以获取为null
6.类似回调函数,一步步返回。这个页面就执行了一遍,即使exceptionfilter捕捉了异常,但是因为index.jsp没有配置授权的事情,所以异常filter中的异常策略authenticationEntryPoint没执行。
  index.jsp访问完毕,我们来调试访问受保护的页面security.jsp,因为acegi进行配置了。上述已经把基本的流程跟大家调通,接下来就是不同之处,当然也是这个过滤连流程。因为访问受保护的资源,所以捕捉没有输入用户名和密码,然后异常交给basic处理,basic认证是弹出框,输入用户名和密码的。
bubuko.com,布布扣
  那我们输入正确有效的用户,测试如下:
  header如下:
  bubuko.com,布布扣
 bubuko.com,布布扣bubuko.com,布布扣
你配置保护urlObjectDefinitionSource获取权限:
    public ConfigAttributeDefinition lookupAttributes(String url) {
        // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
        int firstQuestionMarkIndex = url.indexOf( "?");

        if (firstQuestionMarkIndex != -1) {
            url = url.substring(0, firstQuestionMarkIndex);
        }

        if (isConvertUrlToLowercaseBeforeComparison()) {
            url = url.toLowerCase();

            if ( logger.isDebugEnabled()) {
                logger.debug( "Converted URL to lowercase, from: ‘" + url + "‘; to: ‘" + url + "‘");
            }
        }

        Iterator iter = requestMap.iterator();

        while (iter.hasNext()) {
            EntryHolder entryHolder = (EntryHolder) iter.next();

            boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);

            if ( logger.isDebugEnabled()) {
                logger.debug( "Candidate is: ‘" + url + "‘; pattern is " + entryHolder.getAntPath() + "; matched="
                    + matched);
            }

            if (matched) {
                return entryHolder.getConfigAttributeDefinition();
            }
        }

        return null;
    }
   进行投票机制:
  关键代码:
     authenticated = SecurityContextHolder.getContext().getAuthentication();
     this. accessDecisionManager .decide(authenticated, object, attr);
     public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
        int result = ACCESS_ABSTAIN;
        Iterator iter = config.getConfigAttributes();

        while (iter.hasNext()) {
            ConfigAttribute attribute = (ConfigAttribute) iter.next();

            if ( this.supports(attribute)) {
                result = ACCESS_DENIED;

                // Attempt to find a matching granted authority
                for ( int i = 0; i < authentication.getAuthorities().length ; i++) {
                    if (attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())) {
                        return ACCESS_GRANTED;
                    }
                }
            }
        }

        return result;
    }
       while (iter.hasNext()) {
            AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
            int result = voter.vote(authentication, object, config);

            switch (result) {
            case AccessDecisionVoter. ACCESS_GRANTED:
                return;

            case AccessDecisionVoter. ACCESS_DENIED:
                deny++;

                break;

            default:
                break;
            }
        }

        if (deny > 0) {
            throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied" ,
                    "Access is denied"));
        }
      上述给的不是特别完整的代码,但是都是很关键的代码。大家可以下载源码,然后自己debug调试,同时我也会把acegi源码附上。
      一般情况下完整的系统很少使用basic认证,因为每个系统都有自己的登陆页,若未登陆应该跳转到登陆页面,若权限不足,应该跳转到accessdefined页面。那我们下篇博客搭建基于表单认证。
       项目源码:点我下载

acegi security实践教程—basic认证之debug调试

原文:http://blog.csdn.net/llhhyy1989/article/details/19767725

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!