CAS自定义认证失败消息

  1. idea 导入cas-overlay-template (因为目前用的JDK版本是1.8的,所有只能选择5.3的cas) 这一步描述下大概过程。
    a. 将pom.xml 放在模块下。
    b. 生成自定义证书放在 resources 下。
    c. 修改部分配置覆盖cas的。(application.yml)
    d. 执行build.cmd 等待启动完成。(Windows 系统)

  2. 自定义身份验证
    自定义认证处理器

    	import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
    	import org.apereo.cas.authentication.PreventedException;
    	import org.apereo.cas.authentication.UsernamePasswordCredential;
    	import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
    	import javax.security.auth.login.FailedLoginException;
    	import java.security.GeneralSecurityException;
    	import java.util.Collections;
    
    	public class CustomAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
    
    public CustomAuthenticationHandler() {
        super("customAuthenticationHandler", null, null, 1);
    }
    
    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException {
    			if ("test".equals(credential.getUsername())) {
    				return this.createHandlerResult(credential, this.principalFactory.createPrincipal(credential.getUsername()), Collections.emptyList());
    			}
    			throw new FailedLoginException("账号错误");
    		}
    	}
    

    注册认证处理器

    	import xxx.CustomAuthenticationHandler;
    	import org.apereo.cas.authentication.*;
    	import org.apereo.cas.configuration.CasConfigurationProperties;
    	import org.springframework.boot.context.properties.EnableConfigurationProperties;
    	import org.springframework.context.annotation.Bean;
    	import org.springframework.context.annotation.Configuration;
    	import javax.annotation.PostConstruct;
    
    	@Configuration
    	@EnableConfigurationProperties(CasConfigurationProperties.class)
    	public class CustomAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer {
    
    		@Bean
    		public AuthenticationHandler myAuthenticationHandler() {
    			return new CustomAuthenticationHandler();
    		}
    
    		@Override
    		public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
    			plan.registerAuthenticationHandler(myAuthenticationHandler());
    		}
    	}
    

    注册配置

    创建src/main/resources/META-INF/spring.factories文件输入一下内容

org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.CustomAuthenticationEventExecutionPlanConfiguration
  1. 自定义认证失败消息
    经过代码跟踪发现是在org.apereo.cas.web.flow.actions.AuthenticationExceptionHandlerAction#handle处理失败消息的。

    	public String handle(final Exception e, final RequestContext requestContext) {
        final MessageContext messageContext = requestContext.getMessageContext();
    
        if (e instanceof AuthenticationException) {
            return handleAuthenticationException((AuthenticationException) e, requestContext);
        }
    
        if (e instanceof AbstractTicketException) {
            return handleAbstractTicketException((AbstractTicketException) e, requestContext);
        }
    
        LOGGER.trace("Unable to translate errors of the authentication exception [{}]. Returning [{}]", e, UNKNOWN);
        final String messageCode = this.messageBundlePrefix + UNKNOWN;
        messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());
        return UNKNOWN;
    }
    

    因为抛出的 FailedLoginException 是 AuthenticationException 的子类,所以看看handleAuthenticationException 方法。

    	protected String handleAuthenticationException(final AuthenticationException e, final RequestContext requestContext) {
        if (e.getHandlerErrors().containsKey(UnauthorizedServiceForPrincipalException.class.getSimpleName())) {
            final URI url = WebUtils.getUnauthorizedRedirectUrlIntoFlowScope(requestContext);
            if (url != null) {
                LOGGER.warn("Unauthorized service access for principal; CAS will be redirecting to [{}]", url);
                return CasWebflowConstants.STATE_ID_SERVICE_UNAUTHZ_CHECK;
            }
        }
    
        final Collection<Class> values = e.getHandlerErrors().values().stream().map(Throwable::getClass).collect(Collectors.toList());
        final String handlerErrorName = this.errors
            .stream()
            .filter(values::contains)
            .map(Class::getSimpleName)
            .findFirst()
            .orElseGet(() -> {
                LOGGER.debug("Unable to translate handler errors of the authentication exception [{}]. Returning [{}]", e, UNKNOWN);
                return UNKNOWN;
            });
    
        final MessageContext messageContext = requestContext.getMessageContext();
        final String messageCode = this.messageBundlePrefix + handlerErrorName;
        messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());
        return handlerErrorName;
    }
    

    上诉代码中的 messageCode 结果是: authenticationFailure.{异常类名} 。所以自定义消息修改对应message就行了。将 messages_zh_CN.properties 文件复制出来,修改 authenticationFailure.FailedLoginException 的值。

    登录失败
    切换用户名登录
    test登录 登录成功

    参考链接 Apereo CAS - Custom Authentication & Attribute Sources

0评论