CAS源码学习

创建TGT解析

String createTicketGrantingTicket(Credentials credentials) throws TicketException;
经过RemoteCentralAuthenticationService代理校验参数后,直接调用CentralAuthenticationServiceImpl的实现逻辑。实现逻辑代码很清爽。

  // inspektr-audit包提供的功能,能够进行操作审计
    @Audit(
        action="TICKET_GRANTING_TICKET",
        actionResolverName="CREATE_TICKET_GRANTING_TICKET_RESOLVER",
        resourceResolverName="CREATE_TICKET_GRANTING_TICKET_RESOURCE_RESOLVER")
    @Profiled(tag = "CREATE_TICKET_GRANTING_TICKET", logFailuresSeparately = false)//自动方法耗时统计
    @Transactional(readOnly = false)//事物处理策略    
    public String createTicketGrantingTicket(final Credentials credentials) throws TicketCreationException {
        Assert.notNull(credentials, "credentials cannot be null");
        try {
            final Authentication authentication = this.authenticationManager
                .authenticate(credentials); //调用认证管理器认证证书
            
            //认证成功即无异常抛出,则进行TGT票据生成。
            final TicketGrantingTicket ticketGrantingTicket = new TicketGrantingTicketImpl(
                this.ticketGrantingTicketUniqueTicketIdGenerator
                    .getNewTicketId(TicketGrantingTicket.PREFIX),
                authentication, this.ticketGrantingTicketExpirationPolicy);
            
            //将TGT票据注册
            this.ticketRegistry.addTicket(ticketGrantingTicket);
            return ticketGrantingTicket.getId();
        } catch (final AuthenticationException e) {
            throw new TicketCreationException(e);
        }
    }

第一步认证凭证

认证凭证的代码如下:

final Authentication authentication = this.authenticationManager
                .authenticate(credentials);

其中,Authentication是个接口,它是认证成功得到的用户信息的一个抽象。他包含了认证请求成工的主要当事人身份,他还包括认证日期和额外参数的map
。AuthenticationManager也是个接口,它是能够认证凭证的管理类的一个抽象。cas-server通过定义纯接口的编码来保持协议的可扩展性。

  • AuthenticationManager
    • AbstractAuthenticationManager 抽象模板类
      • AuthenticationManagerImpl 最常用的实现,遍历寻找证书处理器,及身份处理器,还会使用AuthenticationAttributesPopulators来尝试填充attributes参数
      • DirectMappingAuthenticationManagerImpl 直接通过凭证类型查找证书
      • LinkedAuthenticationHandlerAndCredentialsToPrincipalResolverAuthenticationManager 串联调用认证handler

AbstractAuthenticationManager约定了AuthenticationManager要做的主要事情模板,其主要方法为:

@Audit(
        action="AUTHENTICATION",
        actionResolverName="AUTHENTICATION_RESOLVER",
        resourceResolverName="AUTHENTICATION_RESOURCE_RESOLVER")
    @Profiled(tag = "AUTHENTICATE", logFailuresSeparately = false)
    public final Authentication authenticate(final Credentials credentials) throws AuthenticationException {
        //认证的具体处理,通过定义对象同时接收两个参数    ,其中authenticateAndObtainPrincipal由具体子类实现
        final Pair<AuthenticationHandler, Principal> pair = authenticateAndObtainPrincipal(credentials);
        // we can only get here if the above method doesn't throw an exception. And if it doesn't, then the pair must not be null.
        final Principal p = pair.getSecond();
        log.info("{} authenticated {} with credential {}.", pair.getFirst(), p, credentials);
        log.debug("Attribute map for {}: {}", p.getId(), p.getAttributes());
        
        //易变的认证信息对象,这个对象中的信息还可以修改
        Authentication authentication = new MutableAuthentication(p);
        if (pair.getFirst()instanceof NamedAuthenticationHandler) {
            final NamedAuthenticationHandler a = (NamedAuthenticationHandler) pair.getFirst();
            authentication.getAttributes().put(AuthenticationManager.AUTHENTICATION_METHOD_ATTRIBUTE, a.getName());
        }
        for (final AuthenticationMetaDataPopulator authenticationMetaDataPopulator : this.authenticationMetaDataPopulators) {
            authentication = authenticationMetaDataPopulator
                .populateAttributes(authentication, credentials);
        }
        
        //提供一个内置map参数不可变的身份认证对象,保证安全性
        return new ImmutableAuthentication(authentication.getPrincipal(),
            authentication.getAttributes());
    }

其中final Pair<AuthenticationHandler, Principal> pair = authenticateAndObtainPrincipal(credentials);很关键.他的具体逻辑由子类实现,通过查看AuthenticationManagerImpl默认认证管理实现类的逻辑代码如下:

@Override
protected Pair<AuthenticationHandler, Principal> authenticateAndObtainPrincipal(final Credentials credentials) throws AuthenticationException {
    boolean foundSupported = false;
    boolean authenticated = false;
    AuthenticationHandler authenticatedClass = null;
    String handlerName;
    
    //寻找支持的处理器,并进行认证
    for (final AuthenticationHandler authenticationHandler : this.authenticationHandlers) {
        if (authenticationHandler.supports(credentials)) {
            foundSupported = true;
            handlerName = authenticationHandler.getClass().getName();
            try {
                if (!authenticationHandler.authenticate(credentials)) {
                    log.info("{} failed to authenticate {}", handlerName, credentials);
                } else {
                    log.info("{} successfully authenticated {}", handlerName, credentials);
                    authenticatedClass = authenticationHandler;
                    authenticated = true;
                    break;
                }
            } catch (final Exception e) {
                handleError(handlerName, credentials, e);
            }
        }
    }

    //凭证不支持的处理
    if (!authenticated) {
        if (foundSupported) {
            throw BadCredentialsAuthenticationException.ERROR;
        }
        throw UnsupportedCredentialsException.ERROR;
    }

    foundSupported = false;

    //凭证支持转化获取具体的认证身份
    for (final CredentialsToPrincipalResolver credentialsToPrincipalResolver : this.credentialsToPrincipalResolvers) {
        if (credentialsToPrincipalResolver.supports(credentials)) {
            final Principal principal = credentialsToPrincipalResolver.resolvePrincipal(credentials);
            log.info("Resolved principal " + principal);
            foundSupported = true;
            if (principal != null) {
                return new Pair<AuthenticationHandler,Principal>(authenticatedClass, principal);
            }
        }
    }

    //身份转化不支持处理
    if (foundSupported) {
        if (log.isDebugEnabled()) {
            log.debug("CredentialsToPrincipalResolver found but no principal returned.");
        }

        throw BadCredentialsAuthenticationException.ERROR;
    }

    log.error("CredentialsToPrincipalResolver not found for " + credentials.getClass().getName());
    throw UnsupportedCredentialsException.ERROR;
}

上段代码中可以发现AuthenticationHandler接口主要是凭证认证的处理类,其实现类结构如下:

  • AuthenticationHandler
    • HttpBasedServiceCredentialsAuthenticationHandler
    • NamedAuthenticationHandler
      • AbstractPreAndPostProcessingAuthenticationHandler
posted @ 2017-07-12 00:00  Alcc  阅读(312)  评论(0编辑  收藏  举报