shiro buji pac4j cas 单点退出不起作用
shiro buji pac4j cas single sign out not work
spring 启动 2.2.5
shiro-spring-boot-web-starter 1.5.1
布吉-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
}
application.yml 共 pac4j1
:
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
提供的 link SLO 的帮助下,我知道 cas 服务器需要将注销请求发送回客户端。
因此,我查看了cas服务器的日志,发现INFO [org.apereo.cas.logout.DefaultLogoutManager] - <Performing logout operations for
。
所以我为 org.apereo.cas.logout
添加了日志,发现关于注销有一些 类:DefaultLogoutManager
、DefaultSingleLogoutServiceLogoutUrlBuilder
、DefaultSingleLogoutServiceMessageHandler
和 SimpleUrlValidator
.
执行注销时,DefaultSingleLogoutServiceLogoutUrlBuilder.determineLogoutUrl
将从注册服务中获取注销url,或者如果原始url是有效的[=,则从cas客户端获取原始url 46=].
所以我的问题是:我没有在服务json文件和来自cas客户端的原始url中定义注销url localhost:8444
这是一个无效的 ipv4。因此,cas 服务器将不会向客户端发送注销请求。
解决方案是:在项目url中使用ip
,而不是在cas客户端的application.yml
中使用localhost
:
cas:
client-name: pac4j1Client
server:
url: https://localhost:8443/cas
project:
url: http://192.168.2.119:8444/pac4j1
为每个 cas 客户端服务 json 文件(尚未尝试)设置了另一个解决方案 logoutUrl
。
spring 启动 2.2.5
shiro-spring-boot-web-starter 1.5.1
布吉-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
}
application.yml 共 pac4j1
:
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
提供的 link SLO 的帮助下,我知道 cas 服务器需要将注销请求发送回客户端。
因此,我查看了cas服务器的日志,发现INFO [org.apereo.cas.logout.DefaultLogoutManager] - <Performing logout operations for
。
所以我为 org.apereo.cas.logout
添加了日志,发现关于注销有一些 类:DefaultLogoutManager
、DefaultSingleLogoutServiceLogoutUrlBuilder
、DefaultSingleLogoutServiceMessageHandler
和 SimpleUrlValidator
.
执行注销时,DefaultSingleLogoutServiceLogoutUrlBuilder.determineLogoutUrl
将从注册服务中获取注销url,或者如果原始url是有效的[=,则从cas客户端获取原始url 46=].
所以我的问题是:我没有在服务json文件和来自cas客户端的原始url中定义注销url localhost:8444
这是一个无效的 ipv4。因此,cas 服务器将不会向客户端发送注销请求。
解决方案是:在项目url中使用ip
,而不是在cas客户端的application.yml
中使用localhost
:
cas:
client-name: pac4j1Client
server:
url: https://localhost:8443/cas
project:
url: http://192.168.2.119:8444/pac4j1
为每个 cas 客户端服务 json 文件(尚未尝试)设置了另一个解决方案 logoutUrl
。