acegi security实践教程—basic认证之debug调试
2014-02-23 21:10
483 查看
debug调试:
[align=left] 运行:http://localhost:8080/acegitest1/index.jsp[/align]
因为web.xml中配置:
1. 进入:FilterToBeanProxy代理类中的doFilter,因为init只执行一次,启动时已经执行一次,所以访问url时,直接直接进入doFilter方法。
2. 进入:目标类filterChainProxy 中的doFilter
[align=left] 这个方法,主要获取aceg配置文件中,用户配置了多少个filter,并且filter顺序以数组形式展示,这样就开始filter过滤连了。[/align]
[align=left]3.进入:过滤连第一个filter,也就是咱们配置的basicProcessingFilter,其中doFilter如下:[/align]
这个关键在于if ((header != null)
&& header.startsWith( "Basic ")),其中basic认证是把用户输入用户名和密码存放到header中,basic认证的。因为这个header为null【稍后在分析header】,所以执行下一个filter。
[align=left]4.进入exceptionfilter[/align]
[align=left]5.进入filterInvocationInterceptor[/align]
跟着进去invoke,然后进入InterceptorStatusToken token = super.beforeInvocation(fi);最后关键处在于ConfigAttributeDefinition
attr = this.obtainObjectDefinitionSource ().getAttributes(object);
[align=left] obtainObjectDefinitionSource 大家眼熟吧,就是acegi配置文件,配置那个文件有那个角色。因为index.jsp没有配置,所以获取为null[/align]
[align=left]6.类似回调函数,一步步返回。这个页面就执行了一遍,即使exceptionfilter捕捉了异常,但是因为index.jsp没有配置授权的事情,所以异常filter中的异常策略authenticationEntryPoint没执行。[/align]
[align=left] index.jsp访问完毕,我们来调试访问受保护的页面security.jsp,因为acegi进行配置了。上述已经把基本的流程跟大家调通,接下来就是不同之处,当然也是这个过滤连流程。因为访问受保护的资源,所以捕捉没有输入用户名和密码,然后异常交给basic处理,basic认证是弹出框,输入用户名和密码的。[/align]
![](https://img-blog.csdn.net/20140223203719203?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGxoaHl5MTk4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
[align=left] 那我们输入正确有效的用户,测试如下:[/align]
[align=left] header如下:[/align]
![](https://img-blog.csdn.net/20140223203805671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGxoaHl5MTk4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20140223203821765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGxoaHl5MTk4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20140223203838734?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGxoaHl5MTk4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
你配置保护urlObjectDefinitionSource获取权限:
[align=left] 进行投票机制:[/align]
[align=left] 关键代码:[/align]
[align=left] 上述给的不是特别完整的代码,但是都是很关键的代码。大家可以下载源码,然后自己debug调试,同时我也会把acegi源码附上。[/align]
[align=left] 一般情况下完整的系统很少使用basic认证,因为每个系统都有自己的登陆页,若未登陆应该跳转到登陆页面,若权限不足,应该跳转到accessdefined页面。那我们下篇博客搭建基于表单认证。[/align]
项目源码:
![](https://img-blog.csdn.net/20140225150051187?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGxoaHl5MTk4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
[align=left] 运行:http://localhost:8080/acegitest1/index.jsp[/align]
因为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()); }
[align=left] 这个方法,主要获取aceg配置文件中,用户配置了多少个filter,并且filter顺序以数组形式展示,这样就开始filter过滤连了。[/align]
[align=left]3.进入:过滤连第一个filter,也就是咱们配置的basicProcessingFilter,其中doFilter如下:[/align]
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。
[align=left]4.进入exceptionfilter[/align]
[align=left]5.进入filterInvocationInterceptor[/align]
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);
[align=left] obtainObjectDefinitionSource 大家眼熟吧,就是acegi配置文件,配置那个文件有那个角色。因为index.jsp没有配置,所以获取为null[/align]
[align=left]6.类似回调函数,一步步返回。这个页面就执行了一遍,即使exceptionfilter捕捉了异常,但是因为index.jsp没有配置授权的事情,所以异常filter中的异常策略authenticationEntryPoint没执行。[/align]
[align=left] index.jsp访问完毕,我们来调试访问受保护的页面security.jsp,因为acegi进行配置了。上述已经把基本的流程跟大家调通,接下来就是不同之处,当然也是这个过滤连流程。因为访问受保护的资源,所以捕捉没有输入用户名和密码,然后异常交给basic处理,basic认证是弹出框,输入用户名和密码的。[/align]
[align=left] 那我们输入正确有效的用户,测试如下:[/align]
[align=left] header如下:[/align]
你配置保护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; }
[align=left] 进行投票机制:[/align]
[align=left] 关键代码:[/align]
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")); }
[align=left] 上述给的不是特别完整的代码,但是都是很关键的代码。大家可以下载源码,然后自己debug调试,同时我也会把acegi源码附上。[/align]
[align=left] 一般情况下完整的系统很少使用basic认证,因为每个系统都有自己的登陆页,若未登陆应该跳转到登陆页面,若权限不足,应该跳转到accessdefined页面。那我们下篇博客搭建基于表单认证。[/align]
项目源码:
相关文章推荐
- acegi security实践教程—form认证之debug调试
- acegi security实践教程—由debug调试来解析session
- acegi security实践教程—logoutFilter应用以及调试
- acegi security实践教程—访问系统中资源前必须登陆系统
- acegi security实践教程—资源角色信息存到放数据库
- android studio debug调试教程
- acegi security实践教程—简单定制logoutFilter
- acegi security实践教程—入门
- Reveal UI调试利器,逆向app的实践教程:Reveal别人的 app(一)
- IntelliJ IDEA使用教程十 Debug调试程序
- acegi security实践教程—form认证
- 微信开发获取出错信息,进行debug错误调试-微信开发教程8
- acegi security实践教程—basic认证
- intellij idea远程debug调试resin4教程
- 汇编语言学习-Dos下的调试工具debug的使用教程
- 汇编语言学习-Dos下的调试工具debug的使用教程
- iOS开发实践教程(二)之真机调试流程
- IntelliJ IDEA 使用教程十二 - Debug 调试多线程程序
- XCode4 的调试定位技巧, 使用Xcode 4编译器设定Release/Debug教程
- Android Studio Debug调试教程