本例使用的cas源码是 7.3.0-SNAPSHOT
页面控制
页面:
登录页:E:\git-repository\cas-server\support\cas-server-support-thymeleaf\src\main\resources\templates\login
E:\git-repository\cas-server\support\cas-server-support-thymeleaf\src\main\resources\templates\fragments\loginform.html
中文资源:
E:\git-repository\cas-server\support\cas-server-support-thymeleaf\src\main\resources\messages_zh_CN.properties
登录错误页:E:\git-repository\cas-server\support\cas-server-support-thymeleaf\src\main\resources\templates\login-error
注销页:E:\git-repository\cas-server\support\cas-server-support-thymeleaf\src\main\resources\templates\logout
webflow配置
Wefflow上下文配置类
E:\git-repository\cas-server\core\cas-server-core-webflow\src\main\java\org\apereo\cas\config\CasWebflowContextConfiguration.java
默认登录Webflow配置类(主要内容在这里)
CAS登录流程的核心配置类
E:\git-repository\cas-server\core\cas-server-core-webflow-api\src\main\java\org\apereo\cas\web\flow\configurer\DefaultLoginWebflowConfigurer.java
在CAS登录流程中,当登录表单提交后,系统会通过以下调用链处理认证请求:
1. 表单提交触发转移
在 createLoginFormView 方法中定义的转移规则生效:
createTransitionForState(state, CasWebflowConstants.TRANSITION_ID_SUBMIT, CasWebflowConstants.STATE_ID_REAL_SUBMIT);
2. 核心处理方法
realSubmit 状态对应的处理方法是:
protected void createRealSubmitAction(final Flow flow) {
val state = createActionState(flow, CasWebflowConstants.STATE_ID_REAL_SUBMIT,
CasWebflowConstants.ACTION_ID_AUTHENTICATION_VIA_FORM_ACTION);
// 转移配置...
}
关键处理类:
AuthenticationViaFormAction (对应 ACTION_ID_AUTHENTICATION_VIA_FORM_ACTION)
3. 认证处理调用链
表单提交后的完整处理流程:AuthenticationViaFormAction.doExecute()
AuthenticationViaFormAction(在support/cas-server-support-actions/src/main/java/org/apereo/cas/config/CasSupportActionsAutoConfiguration.java定义)
实际上是交给core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/actions/InitialAuthenticationAction.java 处理
// 处理:E:\git-repository\cas-server\core\cas-server-core-webflow-api\src\main\java\org\apereo\cas\web\flow\actions\AbstractAuthenticationAction.java
=======>doExecuteInternal()方法
1.自适应策略检查
2.先尝试服务票据解析(可能已有有效会话)
3.需要完整认证时,返回认证成功或失败事件 initialAuthenticationAttemptWebflowEventResolver.resolveSingle(requestContext);
4.事件钩子机制
=======>resolveSingle(requestContext);
1、凭证提取:从请求上下文中获取UsernamePasswordCredential等凭证对象
2、认证委托:调用AuthenticationManager.authenticate()
3、结果转换:将认证结果映射为Webflow事件
=======>DefaultAuthenticationManager.authenticateInternal()
地址:E:\git-repository\cas-server\core\cas-server-core-authentication-api\src\main\java\org\apereo\cas\authentication\DefaultAuthenticationManager.java
1、根据事务特征(如服务URL)获取适用的认证处理器
2、双重循环认证
protected AuthenticationBuilder authenticateInternal(final AuthenticationTransaction transaction) throws Throwable { val credentials = transaction.getCredentials(); LOGGER.debug("Authentication credentials provided for this transaction are [{}]", credentials); // 空凭证检查 if (credentials.isEmpty()) { LOGGER.error("Resolved authentication handlers for this transaction are empty"); throw new AuthenticationException("Resolved credentials for this transaction are empty"); } // 构建认证结果容器 val authenticationBuilder = new DefaultAuthenticationBuilder(NullPrincipal.getInstance()); credentials.forEach(authenticationBuilder::addCredential); // 根据事务特征(如服务URL)获取适用的认证处理器 // 典型处理器: // LdapAuthenticationHandler(LDAP认证) // JdbcAuthenticationHandler(数据库认证) // X509AuthenticationHandler(证书认证) val handlerSet = authenticationEventExecutionPlan.resolveAuthenticationHandlers(transaction); LOGGER.debug("Candidate resolved authentication handlers for this transaction are [{}]", handlerSet); try { // 双重循环认证 // 凭证级循环 for (val credential : credentials) { LOGGER.debug("Attempting to authenticate credential [{}]", credential); // 处理器级循环 val itHandlers = handlerSet.iterator(); var proceedWithNextHandler = true; while (proceedWithNextHandler && itHandlers.hasNext()) { val handler = itHandlers.next(); if (handler.supports(credential)) { try { val resolver = getPrincipalResolverLinkedToHandlerIfAny(handler, transaction); LOGGER.debug("Attempting authentication of [{}] using [{}]", credential.getId(), handler.getName()); // 认证执行核心 // 凭证验证:调用 handler.authenticate(credential) // 主体解析:通过 PrincipalResolver 转换认证结果 // 结果收集:将成功/失败证据存入 authenticationBuilder authenticateAndResolvePrincipal(authenticationBuilder, credential, resolver, handler, transaction.getService()); val authnResult = authenticationBuilder.build(); val executionResult = evaluateAuthenticationPolicies(authnResult, transaction, handlerSet); proceedWithNextHandler = !executionResult.isSuccess(); } catch (final GeneralSecurityException e) { handleAuthenticationException(e, handler.getName(), authenticationBuilder); proceedWithNextHandler = shouldAuthenticationChainProceedOnFailure(transaction, e); } catch (final Exception e) { LOGGER.error("Authentication has failed. Credentials may be incorrect or CAS cannot " + "find authentication handler that supports [{}] of type [{}]. Examine the configuration to " + "ensure a method of authentication is defined and analyze CAS logs at DEBUG level to trace " + "the authentication event.", credential, credential.getClass().getSimpleName()); handleAuthenticationException(e, handler.getName(), authenticationBuilder); proceedWithNextHandler = shouldAuthenticationChainProceedOnFailure(transaction, e); } } else { LOGGER.debug("Authentication handler [{}] does not support the credential type [{}].", handler.getName(), credential); } } } // 策略评估 evaluateFinalAuthentication(authenticationBuilder, transaction, handlerSet); return authenticationBuilder; } finally { for (val handler : handlerSet) { if (handler.isDisposable() && handler instanceof final DisposableBean db) { db.destroy(); } } } }
=======>QueryDatabaseAuthenticationHandler.authenticateUsernamePasswordInternal()
E:\git-repository\cas-server\support\cas-server-support-jdbc-authentication\src\main\java\org\apereo\cas\jdbc\QueryDatabaseAuthenticationHandler.java
1. 凭证提取
2. 数据库查询
3. 密码验证策略
4. 账户状态检查
5. 主体构建

浙公网安备 33010602011771号