- 前:CASクラスタ[1] -理論(CASアーキテクチャ、HTTPS、SSL、TLS、非対称暗号化、証明書、CA、握手)、OpenSSLを、CAS(認証、暗号化ポリシーを指定します)
- 次へ:CASクラスタ[3] -カスタムテーマ、サービス管理と構成の
リファレンス: - カスタムログインのCASバージョンの5.2倍、複数のデータソースログイン-yellowcong
- CASシングルサインオン(4) - カスタム認証ログオンポリシー
- CASシングルサインオン(E) - サービス管理および構成管理
githubの:
カスタムチェックポリシー
#継承AbstractUsernamePasswordAuthenticationHandler
公式認定戦略は、我々は、認証検証戦略をカスタマイズできるようにする必要がある、多くの場合、十分ではありません
主に政策によるカスタム構成は、CASの現実、デザインを変更し、CASでAuthenticationHandlerによって目的を達成するために、データソースを傍受するカスタム認証戦略を登録します。
それは、次の3つのステップに分かれています。
- デザイン独自の認証データ処理プログラム
- 登録CAS認証エンジンに認証インターセプター
- 変更の認定コンフィギュレーションCASへ
まず、依存ライブラリを追加する必要があります。
<!-- Custom Authentication -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-authentication-api</artifactId>
<version>${cas.version}</version>
</dependency>
<!-- Custom Configuration -->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration-api</artifactId>
<version>${cas.version}</version>
</dependency>
我々は唯一の認証モードは達成するために、伝統的なユーザ名とパスワードである場合はAbstractUsernamePasswordAuthenticationHandler
、インスタンスのために、この抽象クラス缶を公式。- 設定-カスタム認証
次のようにその後、我々は、我々自身の実装クラスCustomAuthenticationHandlerをカスタマイズ
package cn.cas;
import cn.cas.utils.UserUtils;
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.MessageDescriptor;
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 org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.util.StringUtils;
import javax.security.auth.login.AccountException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author lawsssscat
*/
public class CustomerAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
public CustomerAuthenticationHandler(
String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
super(name, servicesManager, principalFactory, order);
}
@Override
protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
UsernamePasswordCredential credential, String originalPassword)
throws GeneralSecurityException, PreventedException {
String username = credential.getUsername();
String password = credential.getPassword();
if (StringUtils.isEmpty(username)) {
throw new AccountException("enter your username");
} else if (StringUtils.isEmpty(password)) {
throw new AccountException("enter your PIN");
}
System.out.println("username:" + username);
System.out.println("password:" + password);
User user = UserUtils.findUser(username);
System.out.println("user:" + user);
if (user == null) {
throw new AccountException("Sorry, username not found !");
}
System.out.println("database username:" + user.getUsername());
System.out.println("database password:" + user.getPassword());
if (!password.equals(user.getPassword())) {
throw new FailedLoginException("Sorry, password not correct !");
}
// 可自定义返回给客户端多个属性信息
HashMap<String, Object> info = new HashMap<>();
info.put("expired", user.getExpired());
// 不能为null,否则提交信息无法认证成功!
List<MessageDescriptor> warning = new ArrayList<>();
return createHandlerResult(credential, this.principalFactory.createPrincipal(username, info), warning);
}
}
どのデータベースにエンティティクラスのユーザー、ツールUserUtilsない接続点に関連して、GitHubの上でそれを見
https://github.com/LawssssCat/v-cas
2つの異なる場所でここに与えられた公式の例でバージョン理由(正式版です)、以来
- まず、のリターン
AuthenticationHandlerExecutionResult
ではなく、HandlerResult
実際には、ソースが同じであるが、新バージョンでは、それを改名しました。 - 第二の点は、createHandlerResult入ってくるwaringsはnullに、または他の成功した認証情報を提出することを失敗した後に、プログラムを実行することはできません!!!
主にコードブロックの着信を通じてCredential
、ユーザー名とパスワードを取得し、クライアントに情報をカスタマイズするユーザーを返します。
ここでは、コードによって、複数の異なる方法のクライアントのカスタム属性情報に戻すことができます。
その後、我々は、構成情報、継承を注入しましたAuthenticationEventExecutionPlanConfigurer
。
package cn.cas;
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.authentication.principal.PrincipalFactory;
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 lawsssscat
*/
@Configuration("CustomAuthenticationConfiguration") // 此需要添加,否则bean会被注册两次(虽然不影响正常运行)
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CustomAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {
@Autowired
@Qualifier("servicesManager")
private ServicesManager servicesManager;
// 验证器交给Spring管理
@Bean
public AuthenticationHandler customerAuthenticationHandler() {
System.out.println("initializating AuthenticationHandler@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
String name = CustomerAuthenticationHandler.class.getName();
ServicesManager servicesManager = this.servicesManager;
PrincipalFactory principalFactory = new DefaultPrincipalFactory();
// 定义为优先优先使用
Integer order = 1;
return new CustomerAuthenticationHandler(name,servicesManager, principalFactory, order) ;
}
// 注册自定义验证器
@Override
public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
plan.registerAuthenticationHandler(customerAuthenticationHandler());
}
}
最後に、我々は/メイン下/ resourcesディレクトリMETA-INFディレクトリSRCで私たちの新しいを持っており、以下では、新しいファイルspring.factories、私たち自身の新しい情報に指定したコンフィギュレーションを作成します。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.cas.CustomAuthenticationConfiguration
-- auto-generated definition
create table sp_manager
(
mg_id int auto_increment comment '主键id'
primary key,
mg_name varchar(32) not null comment '名称',
mg_pwd char(32) not null comment '密码',
mg_salt char(36) not null comment 'salt',
mg_time int unsigned not null comment '注册时间',
role_id tinyint(11) default 0 not null comment '角色id',
mg_mobile varchar(32) null,
mg_email varchar(64) null,
mg_expired tinyint(2) default 0 null comment '0:表示启用 1:表示过期',
mg_disabled tinyint(2) default 0 null comment '0:表示启用 1:表示禁用'
)
comment '管理员表';
、アプリケーションを起動し、ユーザー名(linken)とパスワード(123456)を入力し、我々は印刷するコンソール・メッセージを参照してください情報を照合、我々はデータをデータベースからランディングページとクエリを送信されたデータから見つけることができ、ログイン認証が成功します!!
#继承AbstractPreAndPostProcessingAuthenticationHandler
実際には上記の連続はちょうど私がユーザー名とパスワードを送信した情報は、その後、どのように認証をカスタマイズすることはない、という問題がありましたか?
ここでは、継承しますAbstractPreAndPostProcessingAuthenticationHandler
。このインターフェイスを
(AbstractUsernamePasswordAuthenticationHandlerは、このクラスが実装されている継承の上に実際には、それがユーザー名とパスワードの単純なチェックです。)
私たちは、カスタム実装する必要がありますのでAbstractPreAndPostProcessingAuthenticationHandler
アクセスして。
例えば、ここで私は新しいですCustomerAuthenticationHandler2
、次のように、クラス:
package cn.cas.authentication.handler;
import cn.cas.model.User;
import cn.cas.utils.UserUtils;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;
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.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.springframework.util.StringUtils;
import javax.security.auth.login.AccountException;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
/**
* @author lawsssscat
*/
@Log4j2
public class CustomerAuthenticationHandler2 extends AbstractPreAndPostProcessingAuthenticationHandler {
public CustomerAuthenticationHandler2(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 AuthenticationHandlerExecutionResult doAuthentication(
Credential credential)
throws GeneralSecurityException, PreventedException {
UsernamePasswordCredential usernamePasswordCredential = (UsernamePasswordCredential) credential;
String username = usernamePasswordCredential.getUsername();
String password = usernamePasswordCredential.getPassword();
if (StringUtils.isEmpty(username)) {
throw new AccountException("enter your username");
} else if (StringUtils.isEmpty(password)) {
throw new AccountException("enter your PIN");
}
log.info("log4j2 is running @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
System.out.println("username:" + username);
System.out.println("password:" + password);
User user = UserUtils.findUser(username);
System.out.println("user:" + user);
if (user == null) {
throw new AccountException("Sorry, username not found !");
}
if (!password.equals(user.getPassword())) {
throw new FailedLoginException("Sorry, password not correct!");
}
@NonNull Principal principal = this.principalFactory.createPrincipal(username);
return createHandlerResult(usernamePasswordCredential, principal);
}
}
ここで私は、単により多くの情報が送信され、ユーザー名とパスワードを取得するための情報、彼らは情報が送信取得することができ、変換資格を実現します。私はそれは問題ではない理解していない後に、ここで説明します。
その後、我々はCustomAuthenticationConfiguration意志CustomerAuthenticationHandlerにCustomerAuthenticationHandler2に変更しました。
// 验证器交给Spring管理
@Bean
public AuthenticationHandler customerAuthenticationHandler() {
System.out.println("initializating AuthenticationHandler@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
String name = CustomerAuthenticationHandler2.class.getName();
ServicesManager servicesManager = this.servicesManager;
PrincipalFactory principalFactory = new DefaultPrincipalFactory();
// 定义为优先优先使用
Integer order = 1;
return new CustomerAuthenticationHandler2(name,servicesManager, principalFactory, order) ;
}
アプリケーションを起動し、あなたは同じ効果が以前に達成することができます見つけることができます。
githubの: