【发布时间】:2020-07-08 02:04:54
【问题描述】:
弹簧靴 2.2.5
shiro-spring-boot-web-starter 1.5.1
buji-pac4j 4.1.1
pac4j-cas 3.8.3
cas 覆盖模板 5.3.
我在tomcat中用https启动cas服务器,在eclipse中启动两个客户端(pac4j1和pac4j2)。
单点登录有效,但single sign out 失败。
以下是我的配置:
我只在 cas 服务器下添加了 一个 service 文件,如下所示:
{
"@class": "org.apereo.cas.services.RegexRegisteredService",
"serviceId": "^(http)://localhost.*",
"name": "local",
"id": 10000003,
"evaluationOrder": 1
}
pac4j1的application.yml:
server:
port: 8444
servlet:
context-path: /pac4j1
cas:
client-name: pac4j1Client
server:
url: https://localhost:8443/cas
project:
url: http://localhost:8444/pac4j1
Pac4jConfig:
@Configuration
public class Pac4jConfig {
@Value("${cas.server.url}")
private String casServerUrl;
@Value("${cas.project.url}")
private String projectUrl;
@Value("${cas.client-name}")
private String clientName;
@Bean("authcConfig")
public Config config(CasClient casClient, ShiroSessionStore shiroSessionStore) {
Config config = new Config(casClient);
config.setSessionStore(shiroSessionStore);
return config;
}
@Bean
public ShiroSessionStore shiroSessionStore(){
return new ShiroSessionStore();
}
@Bean
public CasClient casClient(CasConfiguration casConfig){
CasClient casClient = new CasClient(casConfig);
casClient.setCallbackUrl(projectUrl + "/callback?client_name=" + clientName);
casClient.setName(clientName);
return casClient;
}
@Bean
public CasConfiguration casConfig(){
final CasConfiguration configuration = new CasConfiguration();
configuration.setLoginUrl(casServerUrl + "/login");
configuration.setProtocol(CasProtocol.CAS20);
configuration.setAcceptAnyProxy(true);
configuration.setPrefixUrl(casServerUrl + "/");
return configuration;
}
}
shiro 配置:
@Configuration
public class ShiroConfig {
@Value("${cas.project.url}")
private String projectUrl;
@Value("${cas.server.url}")
private String casServerUrl;
@Value("${cas.client-name}")
private String clientName;
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(Pac4jSubjectFactory subjectFactory, CasRealm casRealm){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(casRealm);
manager.setSubjectFactory(subjectFactory);
return manager;
}
@Bean
public CasRealm casRealm(){
CasRealm realm = new CasRealm();
realm.setClientName(clientName);
realm.setCachingEnabled(false);
realm.setAuthenticationCachingEnabled(false);
realm.setAuthorizationCachingEnabled(false);
return realm;
}
@Bean
public Pac4jSubjectFactory subjectFactory(){
return new Pac4jSubjectFactory();
}
@Bean
public FilterRegistrationBean<SingleSignOutFilter> singleSignOutFilter() {
FilterRegistrationBean<SingleSignOutFilter> bean = new FilterRegistrationBean<SingleSignOutFilter>();
bean.setName("singleSignOutFilter");
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(casServerUrl);
singleSignOutFilter.setIgnoreInitConfiguration(true);
bean.setFilter(singleSignOutFilter);
bean.addUrlPatterns("/*");
bean.setEnabled(true);
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
@Bean
public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean() {
FilterRegistrationBean<DelegatingFilterProxy> filterRegistration = new FilterRegistrationBean<DelegatingFilterProxy>();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD);
return filterRegistration;
}
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/", "securityFilter");
filterChainDefinitionMap.put("/index", "securityFilter");
filterChainDefinitionMap.put("/callback", "callbackFilter");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**","anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager, Config config) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
loadShiroFilterChain(shiroFilterFactoryBean);
Map<String, Filter> filters = new HashMap<>(3);
SecurityFilter securityFilter = new SecurityFilter();
securityFilter.setConfig(config);
securityFilter.setClients(clientName);
filters.put("securityFilter", securityFilter);
MyCallbackFilter callbackFilter = new MyCallbackFilter();
callbackFilter.setConfig(config);
callbackFilter.setDefaultUrl(projectUrl);
filters.put("callbackFilter", callbackFilter);
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setConfig(config);
logoutFilter.setCentralLogout(true);
logoutFilter.setLocalLogout(true);
logoutFilter.setDefaultUrl(projectUrl + "/callback?client_name=" + clientName);
filters.put("logout",logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
return shiroFilterFactoryBean;
}
}
cas server 的application.properties 是默认值,cas server 使用 https(https://localhost:8443/cas) 而 cas clients 是 http(http://localhost:8444/pac4j1)。
我哪里错了?
【问题讨论】:
-
客户端应用程序有自己的会话吗?
-
@leopal 你的意思是我需要在客户端应用程序中明确设置会话吗?我应该在哪里以及如何设置?我定义了扩展
Pac4jRealm的CasRealm,扩展了CallbackFilter的MyCallbackFilter,扩展了CasClient的MyCasClient,Pac4jConfig和ShiroConfig。 -
好吧,我不熟悉你的堆栈,但我可以提供一些有用的网址。结帐SLO 和SingleSignOutFilter 的
java-cas-client。您可能必须为您的案例实施类似的操作。我希望我能帮助你更多。 -
@leopal 非常感谢您,您提供的链接非常有用,我从中得到了提示。
标签: spring-boot single-sign-on cas shiro pac4j