创建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 抽象模板类
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