本文共 5276 字,大约阅读时间需要 17 分钟。
原文地址,转载请注明出处: ©
我们在使用SSO单点登录的时候不只是验证一下用户名和密码是否一致,有时候还需要验证一些别的校验,那么这一张讲一下如何自定义验证器。
自定义验证很重要,因为我们后续的很多功能,都是基于自定义验证。 CAS服务器的org.apereo.cas.authentication.AuthenticationManager负责基于提供的凭证信息进行用户认证。与Spring Security很相似,实际的认证委托给了一个或多个实现了org.apereo.cas.authentication.AuthenticationHandler接口的处理类。在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。 CAS内置了一些AuthenticationHandler实现类,如下图所示,QueryDatabaseAuthenticationHandler中提供了基于jdbc的用户认证。 如果需要实现自定义登录,只需要实现org.apereo.cas.authentication.AuthenticationHandler接口即可。当然也可以利用已有的实现,比如创建一个继承自org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler的类。下面我们就来实现自定义验证。org.apereo.cas cas-server-core-authentication ${cas.version} org.apereo.cas cas-server-core-authentication-api ${cas.version} org.apereo.cas cas-server-core-webflow ${cas.version}
在此只验证是不是admin用户,其他用户不让登录。
package com.wangsaichao.cas.custom;import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;import org.apereo.cas.authentication.Credential;import org.apereo.cas.authentication.PreventedException;import org.apereo.cas.authentication.UsernamePasswordCredential;import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;import org.apereo.cas.authentication.principal.PrincipalFactory;import org.apereo.cas.services.ServicesManager;import javax.security.auth.login.AccountNotFoundException;import java.security.GeneralSecurityException;import java.util.ArrayList;import java.util.Collections;/** * @author: wangsaichao * @date: 2018/7/21 * @description: 自定义验证器 */public class MyAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler{ public MyAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) { super(name, servicesManager, principalFactory, order); } @Override protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException { if("admin".equals(credential.getUsername())){ return createHandlerResult(credential, this.principalFactory.createPrincipal(credential.getUsername()), new ArrayList<>(0)); }else{ throw new AccountNotFoundException("必须是admin用户才允许通过"); } }}
package com.wangsaichao.cas.config;import com.wangsaichao.cas.custom.MyAuthenticationHandler;import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;import org.apereo.cas.authentication.AuthenticationHandler;import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;import org.apereo.cas.configuration.CasConfigurationProperties;import org.apereo.cas.services.ServicesManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author: wangsaichao * @date: 2018/7/21 * @description: 注册验证器 */@Configuration("myAuthenticationConfiguration")@EnableConfigurationProperties(CasConfigurationProperties.class)public class MyAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer { @Autowired private CasConfigurationProperties casProperties; @Autowired @Qualifier("servicesManager") private ServicesManager servicesManager; /** * 将自定义验证器注册为Bean * @return */ @Bean public AuthenticationHandler myAuthenticationHandler() { MyAuthenticationHandler handler = new MyAuthenticationHandler(MyAuthenticationHandler.class.getSimpleName(), servicesManager, new DefaultPrincipalFactory(), 1); return handler; } /** * 注册验证器 * @param plan */ @Override public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) { plan.registerAuthenticationHandler(myAuthenticationHandler()); }}
在resources\META-INF\spring.factories中配置该类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangsaichao.cas.config.MyAuthenticationConfiguration
使用test/123456登录
注意:
结果可能很奇怪,使用test竟然可以登录,那我们自定义验证器有什么用呢?上面我们说了:在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。也就是说在执行的过程中,肯定有一个authenticationHandlers执行成功了,通过debug发现,PolicyBasedAuthenticationManager中如下截图: 为什么会出现这种情况,还记得我们上一篇博客中配置jdbc验证,以及密码加盐处理,在application.properties中有配置以下两中开头的配置: cas.authn.jdbc.query[0].* 和 cas.authn.jdbc.encode[0].* 分别对应了:QueryDatabaseAuthenticationHandler 和 QueryAndEncodeDatabaseAuthenticationHandler 其中使用test/123456用户登录QueryAndEncodeDatabaseAuthenticationHandler这个处理器执行成功了,所以就登录成功。 所以我们在使用自定义验证器的时候,查询数据库操作,要自己实现,而不能使用cas自带的,包括密码加密等。
将application.properties中jdbc相关 和 密码加盐相关配置注释, 再次使用admin 和 test 账户测试。密码随便写,因为并没有走数据库校验。
admin可以登录。 test不可以登录,认证失败。