参考:
https://blog.youkuaiyun.com/Anumbrella/article/details/81590595
1.依赖:
<!-- 自定义认证的方式 begin -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-webflow</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-oauth-webflow</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-authentication</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp-config</artifactId>
<version>${cas.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-web</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-pac4j-webflow</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration</artifactId>
<version>5.2.1</version>
</dependency>
2.实现AbstractPreAndPostProcessingAuthenticationHandler接口
import com.ohaotian.tydic.pojo.User;
import org.apereo.cas.authentication.*;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.security.auth.login.AccountException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyHandlerAuthentication extends AbstractPreAndPostProcessingAuthenticationHandler {
public MyHandlerAuthentication(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
super(name, servicesManager, principalFactory, order);
}
@Override
public boolean supports(Credential credential) {
//判断传递过来的Credential 是否是自己能处理的类型
return credential instanceof UsernamePasswordCredential;
}
@Override
protected HandlerResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
UsernamePasswordCredential usernamePasswordCredentia = (UsernamePasswordCredential) credential;
String username = usernamePasswordCredentia.getUsername();
String password = usernamePasswordCredentia.getPassword();
System.out.println("输入的username : " + username);
System.out.println("输入的password : " + password);
// JDBC模板依赖于连接池来获得数据的连接,所以必须先要构造连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/cas");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 创建JDBC模板
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
String sql = "SELECT * FROM user WHERE username = ?";
User info = (User) jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class));
System.out.println("查出来的username : "+ info.getUsername());
System.out.println("查出来的password : "+ info.getPassword());
if (info == null) {
throw new AccountException("Sorry, username not found!");
}
if (!info.getPassword().equals(password)) {
throw new FailedLoginException("Sorry, password not correct!");
} else {
final List<MessageDescriptor> list = new ArrayList<>();
return createHandlerResult(usernamePasswordCredentia,
this.principalFactory.createPrincipal(username, Collections.emptyMap()), list);
}
}
}
3.接着我们注入配置信息,继承AuthenticationEventExecutionPlanConfigurer
import com.ohaotian.tydic.handler.MyHandlerAuthentication;
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 anumbrella
*/
@Configuration("CustomAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CustomAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {
@Autowired
private CasConfigurationProperties casProperties;
@Autowired
@Qualifier("servicesManager") //若有一个service有两个实现类(@service("xxx")区别),@Qualifier指定使用哪个实现类
private ServicesManager servicesManager;
@Bean
public AuthenticationHandler myAuthenticationHandler() {
// 参数: name, servicesManager, principalFactory, order
// 定义为优先使用它进行认证
return new MyHandlerAuthentication(MyHandlerAuthentication.class.getName(),
servicesManager, new DefaultPrincipalFactory(), 1);
}
@Override
public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
plan.registerAuthenticationHandler(myAuthenticationHandler());
}
}
4.我们在src/main/resources目录下新建META-INF目录,同时在下面新建spring.factories文件,将配置指定为我们自己新建的信息。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ohaotian.tydic.Configuration.CustomAuthenticationConfiguration
注:
1.如果要实现多个自定义认证只需要将第二,三部,重复一下,在第四步加上逗号和类的reference就ok.
2.认证顺序:
2.1 自定义认证>application.properties里配的认证
2.2 如果有多个自定义认证:
自定义认证之间的顺序 通过xxxConfiguration中配,小的优先级高 0>1