前言:
该篇教程描述如何搭建CAS5.3.x集群操作,由于官方文档并没有贴出集群搭建方案,所以本博主根据源码剖析解决该问题。
文档并没有深入浅出说明原理,直接贴代码用于快速上手学习。
学习CAS5.x 推荐看 以下两个博主文章
此博主文章:https://blog.csdn.net/u010475041/article/category/7156505
此博主文章:https://blog.csdn.net/yelllowcong
全部基于springboot开发,请存在此基础再学习!
该教程由本博主(Garc)首发,所以转载请说明原处,谢谢!!
该教程分为两个部分,衔接第一篇
1.TerminateSessionAction 自定义,解决集群部署随机出现不能退出登录问题
2.解决集群部署密码找回 token在其他节点不生效问题
PS:请按顺序一步一步来
如果发现CAS不能打印info日志,增加一个AsyncLogger指定自己的工程package就好了
以下所有的 configuration 都需要配置spring ,使用spring aop 配置
配置文件目录:src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hpay.sso.support.auth.config.RedisTicketRegistryConfiguration,\
com.hpay.sso.support.auth.config.CasSupportActionsConfiguration,\
com.hpay.sso.support.auth.config.JdbcPasswordManagementConfiguration,\
com.hpay.sso.config.RedisCacheConfig,\
com.hpay.sso.config.SpringSessionRedisConfig
本博主在使用集群登录退出操作发现有时成功有时失败,后来跟源码定位问题发现是TerminateSessionAction获取TGT时
requestScope 当中不存在TGT_id,所以通过使用session解决问题,但是在解决过程中发现并不容易,所以将处理方式写出来。
请直接看代码
maven 依赖版本:
org.apereo.cas
cas-server-core
${cas.version}
org.pac4j
pac4j-core
3.0.1
springboot 配置:
该配置是为了将源码的springboot 管理Bean的 config配置排除掉准备使用自定义的,
如果省去该操作,无法将自定义对象注入进spring
spring.autoconfigure.exclude=org.apereo.cas.web.config.CasSupportActionsConfiguration
自定义TerminateSessionAction:
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.configuration.model.core.logout.LogoutProperties;
import org.apereo.cas.logout.LogoutRequest;
import org.apereo.cas.util.Pac4jUtils;
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator;
import org.apereo.cas.web.support.WebUtils;
import org.pac4j.core.profile.ProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.action.EventFactorySupport;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
public class TerminateSessionAction extends AbstractAction {
private static final Logger LOGGER = LoggerFactory.getLogger(TerminateSessionAction.class);
public static final String REQUEST_PARAM_LOGOUT_REQUEST_CONFIRMED = "LogoutRequestConfirmed";
private final EventFactorySupport eventFactorySupport = new EventFactorySupport();
@Resource
private CentralAuthenticationService centralAuthenticationService;
@Resource
private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
@Resource
private CookieRetrievingCookieGenerator warnCookieGenerator;
private LogoutProperties logoutProperties;
public TerminateSessionAction(LogoutProperties logout) {
this.logoutProperties = logout;
}
public Event doExecute(RequestContext requestContext) {
boolean terminateSession = true;
if (this.logoutProperties.isConfirmLogout()) {
terminateSession = isLogoutRequestConfirmed(requestContext);
}
return terminateSession ? this.terminate(requestContext) : this.eventFactorySupport.event(this, "warn");
}
public Event terminate(RequestContext context) {
try {
HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context);
HttpServletResponse response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
String tgtId = WebUtils.getTicketGrantingTicketId(context);
if (StringUtils.isBlank(tgtId)) {
tgtId = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request);
}
//解决集群登出问题
if (StringUtils.isBlank(tgtId)){
tgtId = (String) request.getSession().getAttribute("ticketGrantingTicketId");
}
if (StringUtils.isNotBlank(tgtId)) {
LOGGER.debug("Destroying SSO session linked to ticket-granting ticket [{}]", tgtId);
List logoutRequests = this.centralAuthenticationService.destroyTicketGrantingTicket(tgtId);
WebUtils.putLogoutRequests(context, logoutRequests);
}
LOGGER.debug("Removing CAS cookies");
this.ticketGrantingTicketCookieGenerator.removeCookie(response);
this.warnCookieGenerator.removeCookie(response);
this.destroyApplicationSession(request, response);
LOGGER.debug("Terminated all CAS sessions successfully.");
if (StringUtils.isNotBlank(this.logoutProperties.getRedirectUrl())) {
WebUtils.putLogoutRedirectUrl(context, this.logoutProperties.getRedirectUrl());
return this.eventFactorySupport.event(this, "redirect");
} else {
return this.eventFactorySupport.success(this);
}
} catch (Throwable var6) {
throw var6;
}
}
protected void destroyApplicationSession(HttpServletRequest request, HttpServletResponse response) {
LOGGER.debug("Destroying application session");
ProfileManager manager = Pac4jUtils.getPac4jProfileManager(request, response);
manager.logout();
HttpSession session = request.getSession(false);
if (session != null) {
Object requestedUrl = session.getAttribute("pac4jRequestedUrl");
session.invalidate();
if (requestedUrl != null && !requestedUrl.equals("")) {
request.getSession(true).setAttribute("pac4jRequestedUrl", requestedUrl);
}
}
}
private static boolean isLogoutRequestConfirmed(RequestContext requestContext) {
HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
return request.getParameterMap().containsKey("LogoutRequestConfirmed");
}
}
使用自定义springboot config管理Bean
import com.hpay.sso.support.auth.action.CreateTicketGrantingTicketAction;
import com.hpay.sso.support.auth.action.TerminateSessionAction;
import com.hpay.sso.support.auth.action.TicketGrantingTicketCheckAction;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
import org.apereo.cas.authentication.AuthenticationSystemSupport;
import org.apereo.cas.authentication.PrincipalElectionStrategy;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.authentication.principal.ServiceFactory;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.logout.LogoutManager;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.ticket.registry.TicketRegistrySupport;
import org.apereo.cas.util.CollectionUtils;
import org.apereo.cas.web.FlowExecutionExceptionResolver;
import org.apereo.cas.web.flow.GatewayServicesManagementCheck;
import org.apereo.cas.web.flow.GenerateServiceTicketAction;
import org.apereo.cas.web.flow.ServiceAuthorizationCheck;
import org.apereo.cas.web.flow.SingleSignOnParticipationStrategy;
import org.apereo.cas.web.flow.actions.InitialAuthenticationAction;
import org.apereo.cas.web.flow.login.GenericSuccessViewAction;
import org.apereo.cas.web.flow.login.InitialAuthenticationRequestValidationAction;
import org.apereo.cas.web.flow.login.InitialFlowSetupAction;
import org.apereo.cas.web.flow.login.InitializeLoginAction;
import org.apereo.cas.web.flow.login.RedirectUnauthorizedServiceUrlAction;
import org.apereo.cas.web.flow.login.SendTicketGrantingTicketAction;
import org.apereo.cas.web.flow.login.ServiceWarningAction;
import org.apereo.cas.web.flow.logout.FrontChannelLogoutAction;
import org.apereo.cas.web.flow.logout.LogoutAction;
import org.apereo.cas.web.flow.logout.LogoutViewSetupAction;
import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver;
import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver;
import org.apereo.cas.web.support.ArgumentExtractor;
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.util.CookieGenerator;
import org.springframework.webflow.execution.Action;
/**
* 该配置覆盖源码配置,实现集群操作。
* 因为有部分Bean无法直接被覆盖,所以才直接覆盖配置再使用自己的Bean
*/
@Configuration("casSupportActionsConfiguration")
@EnableConfigurationProperties({CasConfigurationProperties.class})
@EnableTransactionManagement(
proxyTargetClass = true
)
public class CasSupportActionsConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(CasSupportActionsConfiguration.class);
@Autowired
@Qualifier("serviceTicketRequestWebflowEventResolver")
private CasWebflowEventResolver serviceTicketRequestWebflowEventResolver;
@Autowired
@Qualifier("initialAuthenticationAttemptWebflowEventResolver")
private CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver;
@Autowired
@Qualifier("servicesManager")
private ServicesManager servicesManager;
@Autowired
@Qualifier("ticketGrantingTicketCookieGenerator")
private ObjectProvider ticketGrantingTicketCookieGenerator;
@Autowired
@Qualifier("warnCookieGenerator")
private ObjectProvider warnCookieGenerator;
@Autowired
private CasConfigurationProperties casProperties;
@Autowired
@Qualifier("webApplicationServiceFactory")
private ServiceFactory webApplicationServiceFactory;
@Autowired
@Qualifier("adaptiveAuthenticationPolicy")
private AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;
@Autowired
@Qualifier("centralAuthenticationService")
private CentralAuthenticationService centralAuthenticationService;
@Autowired
@Qualifier("defaultAuthenticationSystemSupport")
private AuthenticationSystemSupport authenticationSystemSupport;
@Autowired
@Qualifier("logoutManager")
private LogoutManager logoutManager;
@Autowired
@Qualifier("defaultTicketRegistrySupport")
private TicketRegistrySupport ticketRegistrySupport;
@Autowired
@Qualifier("rankedAuthenticationProviderWebflowEventResolver")
private CasWebflowEventResolver rankedAuthenticationProviderWebflowEventResolver;
@Autowired
@Qualifier("authenticationServiceSelectionPlan")
private AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies;
@Autowired
@Qualifier("singleSignOnParticipationStrategy")
private SingleSignOnParticipationStrategy webflowSingleSignOnParticipationStrategy;
@Autowired
@Qualifier("principalElectionStrategy")
private PrincipalElectionStrategy principalElectionStrategy;
public CasSupportActionsConfiguration() {
}
@Bean
@RefreshScope
public HandlerExceptionResolver errorHandlerResolver() {
return new FlowExecutionExceptionResolver();
}
@ConditionalOnMissingBean(
name = {"authenticationViaFormAction"}
)
@Bean
@RefreshScope
public Action authenticationViaFormAction() {
return new InitialAuthenticationAction(this.initialAuthenticationAttemptWebflowEventResolver, this.serviceTicketRequestWebflowEventResolver, this.adaptiveAuthenticationPolicy);
}
@RefreshScope
@ConditionalOnMissingBean(
name = {"serviceAuthorizationCheck"}
)
@Bean
public Action serviceAuthorizationCheck() {
return new ServiceAuthorizationCheck(this.servicesManager, this.authenticationRequestServiceSelectionStrategies);
}
@RefreshScope
@ConditionalOnMissingBean(
name = {"sendTicketGrantingTicketAction"}
)
@Bean
public Action sendTicketGrantingTicketAction() {
return new SendTicketGrantingTicketAction(this.centralAuthenticationService, (CookieRetrievingCookieGenerator)this.ticketGrantingTicketCookieGenerator.getIfAvailable(), this.webflowSingleSignOnParticipationStrategy);
}
@RefreshScope
@Bean
@ConditionalOnMissingBean(
name = {"logoutAction"}
)
public Action logoutAction() {
return new LogoutAction(this.webApplicationServiceFactory, this.servicesManager, this.casProperties.getLogout());
}
@ConditionalOnMissingBean(
name = {"initializeLoginAction"}
)
@Bean
@RefreshScope
public Action initializeLoginAction() {
return new InitializeLoginAction(this.servicesManager);
}
@RefreshScope
@Bean
@Autowired
@ConditionalOnMissingBean(
name = {"initialFlowSetupAction"}
)
public Action initialFlowSetupAction(@Qualifier("argumentExtractor") ArgumentExtractor argumentExtractor) {
return new InitialFlowSetupAction(CollectionUtils.wrap(argumentExtractor), this.servicesManager, this.authenticationRequestServiceSelectionStrategies, (CookieRetrievingCookieGenerator)this.ticketGrantingTicketCookieGenerator.getIfAvailable(), (CookieRetrievingCookieGenerator)this.warnCookieGenerator.getIfAvailable(), this.casProperties);
}
@RefreshScope
@Bean
@ConditionalOnMissingBean(
name = {"initialAuthenticationRequestValidationAction"}
)
public Action initialAuthenticationRequestValidationAction() {
return new InitialAuthenticationRequestValidationAction(this.rankedAuthenticationProviderWebflowEventResolver);
}
@RefreshScope
@Bean
@ConditionalOnMissingBean(
name = {"genericSuccessViewAction"}
)
public Action genericSuccessViewAction() {
return new GenericSuccessViewAction(this.centralAuthenticationService, this.servicesManager, this.webApplicationServiceFactory, this.casProperties.getView().getDefaultRedirectUrl());
}
@RefreshScope
@Bean
@ConditionalOnMissingBean(
name = {"redirectUnauthorizedServiceUrlAction"}
)
public Action redirectUnauthorizedServiceUrlAction() {
return new RedirectUnauthorizedServiceUrlAction(this.servicesManager);
}
@Bean
@RefreshScope
@ConditionalOnMissingBean(
name = {"generateServiceTicketAction"}
)
public Action generateServiceTicketAction() {
return new GenerateServiceTicketAction(this.authenticationSystemSupport, this.centralAuthenticationService, this.ticketRegistrySupport, this.authenticationRequestServiceSelectionStrategies, this.servicesManager, this.principalElectionStrategy);
}
@Bean
@ConditionalOnMissingBean(
name = {"gatewayServicesManagementCheck"}
)
@RefreshScope
public Action gatewayServicesManagementCheck() {
return new GatewayServicesManagementCheck(this.servicesManager);
}
@Bean
@ConditionalOnMissingBean(
name = {"frontChannelLogoutAction"}
)
public Action frontChannelLogoutAction() {
return new FrontChannelLogoutAction(this.logoutManager);
}
@RefreshScope
@Bean
public Action terminateSessionAction() {
return new TerminateSessionAction(this.casProperties.getLogout());
}
@Bean
@ConditionalOnMissingBean(
name = {"ticketGrantingTicketCheckAction"}
)
public Action ticketGrantingTicketCheckAction() {
return new TicketGrantingTicketCheckAction();
}
@RefreshScope
@ConditionalOnMissingBean(
name = {"createTicketGrantingTicketAction"}
)
@Bean
public Action createTicketGrantingTicketAction() {
return new CreateTicketGrantingTicketAction();
}
@Bean
public Action logoutViewSetupAction() {
return new LogoutViewSetupAction(this.casProperties);
}
@Bean
@ConditionalOnMissingBean(
name = {"serviceWarningAction"}
)
@RefreshScope
public Action serviceWarningAction() {
return new ServiceWarningAction(this.centralAuthenticationService, this.authenticationSystemSupport, this.ticketRegistrySupport, (CookieGenerator)this.warnCookieGenerator.getIfAvailable(), this.principalElectionStrategy);
}
}
maven 依赖:
org.apereo.cas
cas-server-support-pm
${cas.version}
springboot application 配置:
该配置是为了将源码的springboot 管理Bean的 config配置排除掉准备使用自定义的,
如果省去该操作,无法将自定义对象注入进spring
spring.autoconfigure.exclude=org.apereo.cas.config.pm.JdbcPasswordManagementConfiguration
自定义JdbcPasswordManagementService:
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.routines.EmailValidator;
import org.apereo.cas.CipherExecutor;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.support.password.PasswordEncoderUtils;
import org.apereo.cas.configuration.model.support.pm.PasswordManagementProperties;
import org.apereo.cas.pm.PasswordChangeBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.sql.DataSource;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class JdbcPasswordManagementService extends BasePasswordManagementService {
private static final Logger LOGGER = LoggerFactory.getLogger(JdbcPasswordManagementService.class);
private final JdbcTemplate jdbcTemplate;
public JdbcPasswordManagementService(CipherExecutor cipherExecutor, String issuer, PasswordManagementProperties passwordManagementProperties, DataSource dataSource) {
super(passwordManagementProperties, cipherExecutor, issuer);
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public boolean changeInternal(Credential credential, PasswordChangeBean bean) {
UsernamePasswordCredential c = (UsernamePasswordCredential)credential;
PasswordEncoder encoder = PasswordEncoderUtils.newPasswordEncoder(this.properties.getJdbc().getPasswordEncoder());
String password = encoder.encode(bean.getPassword());
int count = this.jdbcTemplate.update(this.properties.getJdbc().getSqlChangePassword(), new Object[]{password, c.getId()});
return count > 0;
}
public String findEmail(String username) {
try {
String email = (String)this.jdbcTemplate.queryForObject(this.properties.getJdbc().getSqlFindEmail(), String.class, new Object[]{username});
if (StringUtils.isNotBlank(email) && EmailValidator.getInstance().isValid(email)) {
return email;
} else {
LOGGER.debug("Username {} not found when searching for email", username);
return null;
}
} catch (EmptyResultDataAccessException var3) {
LOGGER.debug("Username {} not found when searching for email", username);
return null;
}
}
public Map getSecurityQuestions(String username) {
String sqlSecurityQuestions = this.properties.getJdbc().getSqlSecurityQuestions();
Map map = new LinkedHashMap();
List
自定义BasePasswordManagementService:
当token解析时,其他节点无法正常解密,未找到原因,最后本博主只好替换成AES加密和解密算法。
AESCoder这段代码就不提供了,也可以用其他加密算法代替。
import com.hpay.sso.support.auth.Crypto.AESCoder;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CipherExecutor;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.configuration.model.support.pm.PasswordManagementProperties;
import org.apereo.cas.pm.InvalidPasswordException;
import org.apereo.cas.pm.PasswordChangeBean;
import org.apereo.cas.pm.PasswordManagementService;
import org.apereo.inspektr.audit.annotation.Audit;
import org.apereo.inspektr.common.web.ClientInfo;
import org.apereo.inspektr.common.web.ClientInfoHolder;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.NumericDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class BasePasswordManagementService implements PasswordManagementService {
private static final Logger LOGGER = LoggerFactory.getLogger(BasePasswordManagementService.class);
protected final PasswordManagementProperties properties;
private final CipherExecutor cipherExecutor;
private final String issuer;
public String parseToken(String token) {
try {
String json = AESCoder.decryptToString(token);
if (json.equals(token)){
json = (String)this.cipherExecutor.decode(token);
}
JwtClaims claims = JwtClaims.parse(json);
if (!claims.getIssuer().equals(this.issuer)) {
LOGGER.error("Token issuer does not match CAS");
return null;
} else if (!claims.getAudience().isEmpty() && ((String)claims.getAudience().get(0)).equals(this.issuer)) {
if (StringUtils.isBlank(claims.getSubject())) {
LOGGER.error("Token has no subject identifier");
return null;
} else {
ClientInfo holder = ClientInfoHolder.getClientInfo();
if (!claims.getStringClaimValue("origin").equals(holder.getServerIpAddress())) {
LOGGER.error("Token origin server IP address does not match CAS");
return null;
} else if (!claims.getStringClaimValue("client").equals(holder.getClientIpAddress())) {
LOGGER.error("Token client IP address does not match CAS");
return null;
} else if (claims.getExpirationTime().isBefore(NumericDate.now())) {
LOGGER.error("Token has expired.");
return null;
} else {
return claims.getSubject();
}
}
} else {
LOGGER.error("Token audience does not match CAS");
return null;
}
} catch (Exception var5) {
LOGGER.error(var5.getMessage(), var5);
return null;
}
}
public String createToken(String to) {
try {
String token = UUID.randomUUID().toString();
JwtClaims claims = new JwtClaims();
claims.setJwtId(token);
claims.setIssuer(this.issuer);
claims.setAudience(this.issuer);
claims.setExpirationTimeMinutesInTheFuture(this.properties.getReset().getExpirationMinutes());
claims.setIssuedAtToNow();
ClientInfo holder = ClientInfoHolder.getClientInfo();
if (holder != null) {
claims.setStringClaim("origin", holder.getServerIpAddress());
claims.setStringClaim("client", holder.getClientIpAddress());
}
claims.setSubject(to);
String json = claims.toJson();
String cipher = AESCoder.encryptToString(json);
if (cipher.equals(json)){
cipher = (String)this.cipherExecutor.encode(json);
}
return cipher;
} catch (Exception var6) {
LOGGER.error(var6.getMessage(), var6);
return null;
}
}
@Audit(
action = "CHANGE_PASSWORD",
actionResolverName = "CHANGE_PASSWORD_ACTION_RESOLVER",
resourceResolverName = "CHANGE_PASSWORD_RESOURCE_RESOLVER"
)
public boolean change(Credential c, PasswordChangeBean bean) throws InvalidPasswordException {
return this.changeInternal(c, bean);
}
public boolean changeInternal(Credential c, PasswordChangeBean bean) throws InvalidPasswordException {
return false;
}
public static List canonicalizeSecurityQuestions(Map questionMap) {
List keys = new ArrayList(questionMap.keySet());
keys.sort(String.CASE_INSENSITIVE_ORDER);
return keys;
}
public BasePasswordManagementService(PasswordManagementProperties properties, CipherExecutor cipherExecutor, String issuer) {
this.properties = properties;
this.cipherExecutor = cipherExecutor;
this.issuer = issuer;
}
}
代码configuration ,用于覆盖原有CAS配置:
import com.hpay.sso.support.auth.pm.JdbcPasswordManagementService;
import org.apereo.cas.CipherExecutor;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.support.JpaBeans;
import org.apereo.cas.pm.PasswordManagementService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration("jdbcPasswordManagementConfiguration")
@EnableConfigurationProperties({CasConfigurationProperties.class})
public class JdbcPasswordManagementConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(JdbcPasswordManagementConfiguration.class);
@Autowired
private CasConfigurationProperties casProperties;
@Autowired
@Qualifier("passwordManagementCipherExecutor")
private CipherExecutor passwordManagementCipherExecutor;
public JdbcPasswordManagementConfiguration() {
}
@Bean
public DataSource jdbcPasswordManagementDataSource() {
return JpaBeans.newDataSource(this.casProperties.getAuthn().getPm().getJdbc());
}
@RefreshScope
@Bean
public PasswordManagementService passwordChangeService() {
return new JdbcPasswordManagementService(this.passwordManagementCipherExecutor, this.casProperties.getServer().getPrefix(), this.casProperties.getAuthn().getPm(), this.jdbcPasswordManagementDataSource());
}
}
请继续看下篇!
第二篇教程内容到此已经结束了,只要根据此教程一步一步操作,就可以实现集群登录操作。
如果想了解更多,可以加QQ群 119170668