acegi security实践教程—basic认证之debug调试
来源:互联网 发布:tscttp244pro标签软件 编辑:程序博客网 时间:2024/06/05 03:16
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认证是弹出框,输入用户名和密码的。
那我们输入正确有效的用户,测试如下:
header如下:
你配置保护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页面。那我们下篇博客搭建基于表单认证。
项目源码:
2 0
- acegi security实践教程—basic认证之debug调试
- acegi security实践教程—form认证之debug调试
- acegi security实践教程—basic认证
- acegi security实践教程—form认证
- acegi security实践教程—由debug调试来解析session
- acegi security实践教程—logoutFilter应用以及调试
- acegi security实践教程—入门
- acegi security实践教程—定制userDetailsService
- acegi security实践教程—简单定制logoutFilter
- acegi security实践教程—把用户信息存放到数据库
- acegi security实践教程—把用户信息存放到数据库
- acegi security实践教程—资源角色信息存到放数据库
- acegi security实践教程—访问系统中资源前必须登陆系统
- acegi security
- Http认证之Basic认证
- 认证模式之Basic模式
- Grails 之 Acegi Plugin 转移到Spring Security Core Plugin
- What is Acegi Security?
- Synchronized (同步) block使用实例
- 【题解】[codeforces round #198 div2]Tourists problem
- 2014年王道论坛研究生机试练习赛(一)
- javascript代理模式,和代码织入
- android,加载一个大的图片到内存
- acegi security实践教程—basic认证之debug调试
- 单片机数字钟
- 周赛反思与总结
- 6.2 保存文件
- 周俏妍缩阴日记------------
- stm32 DMA初始化选项研究
- 《30天自制操作系统》学习笔记——第十一天
- UVALive - 5902 Movie collection
- log4j.properties配置文件