Spring源代码解析(九):Spring Acegi框架鉴权的实现

来源:互联网 发布:翼支付刷单软件 编辑:程序博客网 时间:2024/05/19 06:48

publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  

  •     throws IOException, ServletException {  
  •     //这里检验是不是符合ServletRequest/SevletResponse的要求   
  •     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;  
  •     //根据HttpServletRequest和HttpServletResponse来进行验证   
  •     if (requiresAuthentication(httpRequest, httpResponse)) {  
  •         if (logger.isDebugEnabled()) {  
  •             logger.debug("Request is to process authentication");  
  •         }  
  •         //这里定义Acegi中的Authentication对象来持有相关的用户验证信息   
  •         Authentication authResult;  
  •   
  •         try {  
  •             onPreAuthentication(httpRequest, httpResponse);  
  •             //这里的具体验证过程委托给子类完成,比如AuthenticationProcessingFilter来完成基于Web页面的用户验证   
  •             authResult = attemptAuthentication(httpRequest);  
  •         } catch (AuthenticationException failed) {  
  •             // Authentication failed   
  •             unsuccessfulAuthentication(httpRequest, httpResponse, failed);  
  •   
  •             return;  
  •         }  
  •   
  •         // Authentication success   
  •         if (continueChainBeforeSuccessfulAuthentication) {  
  •             chain.doFilter(request, response);  
  •         }  
  •         //完成验证后的后续工作,比如跳转到相应的页面   
  •         successfulAuthentication(httpRequest, httpResponse, authResult);  
  •   
  •         return;  
  •     }  
  •   
  •     chain.doFilter(request, response);  
  • }       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)        throws IOException, ServletException {        //这里检验是不是符合ServletRequest/SevletResponse的要求        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;        //根据HttpServletRequest和HttpServletResponse来进行验证        if (requiresAuthentication(httpRequest, httpResponse)) {            if (logger.isDebugEnabled()) {                logger.debug("Request is to process authentication");            }            //这里定义Acegi中的Authentication对象来持有相关的用户验证信息            Authentication authResult;            try {                onPreAuthentication(httpRequest, httpResponse);                //这里的具体验证过程委托给子类完成,比如AuthenticationProcessingFilter来完成基于Web页面的用户验证                authResult = attemptAuthentication(httpRequest);            } catch (AuthenticationException failed) {                // Authentication failed                unsuccessfulAuthentication(httpRequest, httpResponse, failed);                return;            }            // Authentication success            if (continueChainBeforeSuccessfulAuthentication) {                chain.doFilter(request, response);            }            //完成验证后的后续工作,比如跳转到相应的页面            successfulAuthentication(httpRequest, httpResponse, authResult);            return;        }        chain.doFilter(request, response);    }

    在AuthenticationProcessingFilter中的具体验证过程是这样的:
    Java代码
  • public Authentication attemptAuthentication(HttpServletRequest request)  
  •     throws AuthenticationException {  
  •     //这里从HttpServletRequest中得到用户验证的用户名和密码   
  •     String username = obtainUsername(request);  
  •     String password = obtainPassword(request);  
  •   
  •     if (username == null) {  
  •         username = "";  
  •     }  
  •   
  •     if (password == null) {  
  •         password = "";  
  •     }  
  •     //这里根据得到的用户名和密码去构造一个Authentication对象提供给AuthenticationManager进行验证,里面包含了用户的用户名和密码信息   
  •     UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);  
  •   
  •     // Place the last username attempted into HttpSession for views   
  •     request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username);  
  •   
  •     // Allow subclasses to set the "details" property   
  •     setDetails(request, authRequest);  
  •     //这里启动AuthenticationManager进行验证过程   
  •     return this.getAuthenticationManager().authenticate(authRequest);  
  • }       public Authentication attemptAuthentication(HttpServletRequest request)        throws AuthenticationException {        //这里从HttpServletRequest中得到用户验证的用户名和密码        String username = obtainUsername(request);        String password = obtainPassword(request);        if (username == null) {            username = "";        }        if (password == null) {            password = "";        }        //这里根据得到的用户名和密码去构造一个Authentication对象提供给AuthenticationManager进行验证,里面包含了用户的用户名和密码信息        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);        // Place the last username attempted into HttpSession for views        request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username);        // Allow subclasses to set the "details" property        setDetails(request, authRequest);        //这里启动AuthenticationManager进行验证过程        return this.getAuthenticationManager().authenticate(authRequest);    }

    在Acegi框架中,进行验证管理的主要类是AuthenticationManager,我们看看它是怎样进行验证管理的 - 验证的调用入口是authenticate在AbstractAuthenticationManager的实现中:
    //这是进行验证的函数,返回一个Authentication对象来记录验证的结果,其中包含了用户的验证信息,权限配置等,同时这个Authentication会以后被授权模块使用
    Java代码
  • //如果验证失败,那么在验证过程中会直接抛出异常   
  •     public final Authentication authenticate(Authentication authRequest)  
  •         throws AuthenticationException {  
  •         try {//这里是实际的验证处理,我们下面使用ProviderManager来说明具体的验证过程,传入的参数authRequest里面已经包含了从HttpServletRequest中得到的用户输入的用户名和密码   
  •             Authentication authResult = doAuthentication(authRequest);  
  •             copyDetails(authRequest, authResult);  
  •   
  •             return authResult;  
  •         } catch (AuthenticationException e) {  
  •             e.setAuthentication(authRequest);  
  •             throw e;  
  •         }  
  •     }   //如果验证失败,那么在验证过程中会直接抛出异常    public final Authentication authenticate(Authentication authRequest)        throws AuthenticationException {        try {//这里是实际的验证处理,我们下面使用ProviderManager来说明具体的验证过程,传入的参数authRequest里面已经包含了从HttpServletRequest中得到的用户输入的用户名和密码            Authentication authResult = doAuthentication(authRequest);            copyDetails(authRequest, authResult);            return authResult;        } catch (AuthenticationException e) {            e.setAuthentication(authRequest);            throw e;        }    }

    在ProviderManager中进行实际的验证工作,假设这里使用数据库来存取用户信息:
    Java代码
  • public Authentication doAuthentication(Authentication authentication)  
  •     throws AuthenticationException {  
  •     //这里取得配置好的provider链的迭代器,在配置的时候可以配置多个provider,这里我们配置的是DaoAuthenticationProvider来说明, 它使用数据库来保存用户的用户名和密码信息。   
  •     Iterator iter = providers.iterator();  
  •   
  •     Class toTest = authentication.getClass();  
  •   
  •     AuthenticationException lastException = null;  
  •   
  •     while (iter.hasNext()) {  
  •         AuthenticationProvider provider = (AuthenticationProvider) iter.next();  
  •   
  •         if (provider.supports(toTest)) {  
  •             logger.debug("Authentication attempt using " + provider.getClass().getName());  
  •             //这个result包含了验证中得到的结果信息   
  •             Authentication result = null;  
  •   
  •             try {//这里是provider进行验证处理的过程   
  •                 result = provider.authenticate(authentication);  
  •                 sessionController.checkAuthenticationAllowed(result);  
  •             } catch (AuthenticationException ae) {  
  •                 lastException = ae;  
  •                 result = null;  
  •             }  
  •   
  •             if (result != null) {  
  •                 sessionController.registerSuccessfulAuthentication(result);  
  •                 publishEvent(new AuthenticationSuccessEvent(result));  
  •   
  •                 return result;  
  •             }  
  •         }  
  •     }  
  •   
  •     if (lastException == null) {  
  •         lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound",  
  •                     new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}"));  
  •     }  
  •   
  •     // 这里发布事件来通知上下文的监听器   
  •     String className = exceptionMappings.getProperty(lastException.getClass().getName());  
  •     AbstractAuthenticationEvent event = null;  
  • 原创粉丝点击