好久没有写cas的文章了,最近也是比较忙,还是就是懒,我们之前讲的篇幅主要是基于cas服务端的,如果搭建好服务端后,没有把cas的客户端整合进来就等于没有用,接下来我们这篇文章我们会讲客户端如何接入cas,这边我们会以java和.net来说,因为这两个客户端接进来的问题会比较多,而其他语言比如python、go、php、node这些客户端接进来是没有这些问题,只要跟着文档的配置就ok了。
对于我们java来讲,其实是分为两种,一种也就是基于xml配置的客户端,另一种是基于注解的spring boot(最近比较流行的)。我们这两个我们都会一一教大家如何配置。
其实在java中最要配置的是以下几个类
1、SingleSignOutHttpSessionListener
2、singleSignOutFilter
3、authenticationFilter
4、cas20ProxyReceivingTicketValidationFilter
5、httpServletRequestWrapperFilter
6、assertionThreadLocalFilter
我们主要是基于这六个cas提供的类来配置,其实这每一个类的大致意思我就不讲了,其实看他们的名称就能看出来大致的意思,我们就直接看如何配置,首先是java的xml配置的方式,这种模式下的话,我们要将我们的配置放在web.xml里面,具体的看下面的代码配置
<filter>
//这个主要是用于退出的fiflter
<filter-name>CAS Single Sign Out Filterfilter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilterfilter-class>
<init-param>
<param-name>casServerUrlPrefixparam-name>
<param-value>https://localhost:8443/casparam-value>
这个地址是cas的地址,只需要到项目cas就可以了,cas其实就是我们的项目名
init-param>
filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListenerlistener-class>
listener>
//这个拦截器的作用主要是校验,如果没通过检验就转到cas/login页面
<filter>
<filter-name>CAS Filterfilter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilterfilter-class>
<init-param>
<param-name>casServerLoginUrlparam-name>
这个是cas的登录地址
<param-value>https://localhost:8443/cas/loginparam-value>
init-param>
<init-param>
这个是客户端地址,也就是你对接cas的客户端的地址,这里只需要到ip+端口就可以,其实如果你看了cas-core的源码就知道这个的作用了,主要是在登录拦截之后会进行转化,也就是将你输入的客户端ip和端口转化为这个填写的,所以最好保证是一致的,千万别一个localhost,一个127.0.0.1
<param-name>serverNameparam-name>
<param-value>http://localhost:8080param-value>
init-param>
filter>
<filter-mapping>
<filter-name>CAS Filterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>CAS Validation Filterfilter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilterfilter-class>
<init-param>
<param-name>casServerUrlPrefixparam-name>
这个和之前讲的一个意思
<param-value>http://localhost:8080/casparam-value>
init-param>
<init-param>
<param-name>serverNameparam-name>
<param-value>http://localhost:8080param-value>
init-param>
filter>
<filter-mapping>
<filter-name>CAS Validation Filterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
这个filter的作用就是存cas服务端传过来的一些信息,我们可以通过这个filter来拿取一些用户信息
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filterfilter-name>
<filter-class>
org.jasig.cas.client.util.HttpServletRequestWrapperFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>CAS Assertion Thread Local Filterfilter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
到这里为止我们cas的配置就已经配置好了,但是我们记得要引入cas的客户端jar包,因为我们会发现我们代码中是没有与cas服务器通信的代码,而这个cas的客户端jar包就是承担与cas服务器通信的责任,所以必须得下载下来。
其实与上面最主要的区别在于,一个是在xml配置的,一个是在配置文件和代码做的,我们直接看下如何配置
1、配置文件,因为我们知道,我们spring boot是将配置和代码分割开来,便于维护,
2、bean,因为在xml中我们可以自己注入进去,但是在spring boot,则需要我们自己手动去写@bean。
配置文件:
spring.cas.sign-out-filters=/* 监听退出的接口,即所有接口都会进行监听
spring.cas.auth-filters=/* 需要拦截的接口
spring.cas.validate-filters=/*
spring.cas.request-wrapper-filters=/*
spring.cas.assertion-filters=/* 表示忽略拦截的接口,也就是不用进行拦截
spring.cas.ignore-filters=/hello|/zz
spring.cas.cas-server-login-url=https://localhost:8443/cas/login
spring.cas.cas-server-url-prefix=https://localhost:8443/cas/
spring.cas.redirect-after-validation=true
spring.cas.use-session=true
spring.cas.server-name=https://localhost:8080
配置文件也就是这些东西,不是很多,官方文档其实也有将的,
1、首先我们要将这些配置先注入到一个实体中
@ConfigurationProperties(prefix ="spring.cas")
public class Casconfig {
static final String separator = ",";
private String validateFilters;
private String signOutFilters;
private String authFilters;
private String assertionFilters;
private String requestWrapperFilters;
private String ignoreFilters;//需要放行的url,多个可以使用|分隔,遵循正则
private String casServerUrlPrefix;
private String casServerLoginUrl;
private String serverName;
private boolean useSession = true;
private boolean redirectAfterValidation = true;
public String getIgnoreFilters() {
return ignoreFilters;
}
public void setIgnoreFilters(String ignoreFilters) {
this.ignoreFilters = ignoreFilters;
}
public List getValidateFilters() {
return Arrays.asList(validateFilters.split(separator));
}
public void setValidateFilters(String validateFilters) {
this.validateFilters = validateFilters;
}
public List getSignOutFilters() {
return Arrays.asList(signOutFilters.split(separator));
}
public void setSignOutFilters(String signOutFilters) {
this.signOutFilters = signOutFilters;
}
public List getAuthFilters() {
return Arrays.asList(authFilters.split(separator));
}
public void setAuthFilters(String authFilters) {
this.authFilters = authFilters;
}
public List getAssertionFilters() {
return Arrays.asList(assertionFilters.split(separator));
}
public void setAssertionFilters(String assertionFilters) {
this.assertionFilters = assertionFilters;
}
public List getRequestWrapperFilters() {
return Arrays.asList(requestWrapperFilters.split(separator));
}
public void setRequestWrapperFilters(String requestWrapperFilters) {
this.requestWrapperFilters = requestWrapperFilters;
}
public String getCasServerUrlPrefix() {
return casServerUrlPrefix;
}
public void setCasServerUrlPrefix(String casServerUrlPrefix) {
this.casServerUrlPrefix = casServerUrlPrefix;
}
public String getCasServerLoginUrl() {
return casServerLoginUrl;
}
public void setCasServerLoginUrl(String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public boolean isRedirectAfterValidation() {
return redirectAfterValidation;
}
public void setRedirectAfterValidation(boolean redirectAfterValidation) {
this.redirectAfterValidation = redirectAfterValidation;
}
public boolean isUseSession() {
return useSession;
}
public void setUseSession(boolean useSession) {
this.useSession = useSession;
}
}
这个实体的数据是直接从我们的配置文件读取的
@Autowired
SpringCasAutoconfig autoconfig;
private static boolean casEnabled = true;
public CasConfig() {
}
@Bean
public SpringCasAutoconfig getSpringCasAutoconfig(){
return new SpringCasAutoconfig();
}
@Bean
public ServletListenerRegistrationBean singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean listener = new ServletListenerRegistrationBean();
listener.setEnabled(casEnabled);
listener.setListener(new SingleSignOutHttpSessionListener());
listener.setOrder(1);
return listener;
}
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new SingleSignOutFilter());
filterRegistration.setEnabled(casEnabled);
if(autoconfig.getSignOutFilters().size()>0)
filterRegistration.setUrlPatterns(autoconfig.getSignOutFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
filterRegistration.setOrder(3);
return filterRegistration;
}
@Bean
public FilterRegistrationBean authenticationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new AuthenticationFilter());
filterRegistration.setEnabled(casEnabled);
if(autoconfig.getAuthFilters().size()>0)
filterRegistration.setUrlPatterns(autoconfig.getAuthFilters());
else
filterRegistration.addUrlPatterns("/*");
if(autoconfig.getIgnoreFilters()!=null){
filterRegistration.addInitParameter("ignorePattern", autoconfig.getIgnoreFilters());
}
filterRegistration.addInitParameter("casServerLoginUrl", autoconfig.getCasServerLoginUrl());
filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
filterRegistration.addInitParameter("useSession", autoconfig.isUseSession()?"true":"false");
filterRegistration.addInitParameter("redirectAfterValidation", autoconfig.isRedirectAfterValidation()?"true":"false");
filterRegistration.setOrder(4);
return filterRegistration;
}
@Bean
public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
filterRegistration.setEnabled(casEnabled);
if(autoconfig.getValidateFilters().size()>0)
filterRegistration.setUrlPatterns(autoconfig.getValidateFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
filterRegistration.setOrder(5);
return filterRegistration;
}
@Bean
public FilterRegistrationBean httpServletRequestWrapperFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
filterRegistration.setEnabled(true);
if(autoconfig.getRequestWrapperFilters().size()>0)
filterRegistration.setUrlPatterns(autoconfig.getRequestWrapperFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(6);
return filterRegistration;
}
@Bean
public FilterRegistrationBean assertionThreadLocalFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new AssertionThreadLocalFilter());
filterRegistration.setEnabled(true);
if(autoconfig.getAssertionFilters().size()>0)
filterRegistration.setUrlPatterns(autoconfig.getAssertionFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(7);
return filterRegistration;
}
其实这里注意的一个问题就是order,我们也知道order的作用其实就是顺序,我们要将退出的拦截器放在在前,因为这样的话,我们的退出请求可以最先被我们的退出拦截器进行拦截处理,如果要进行单点退出的时候。
到这里我们整合java客户端的代码和配置已经完成 了,其实不会很难。
1、登录成功后验证ticket的时候报ssl证书的问题?
因为我们知道cas推荐我们使用https来搭建,我们也知道http和https的区别,这边就不介绍了,其实最主要就是证书,如果使用https的话,我们之前也已经交大家如何使用keytool来生成证书,因为我们是自己生成的证书,所以我们客户端进行登录的时候会报st的问题,其实就是我们的证书没有导入到jdk中,这时候我们只需要将我们的证书导入到jdk中就没有问题了。
2、验证st不通过?
上面这个其实也是验证st不通过的问题,但是他主要是证书的问题,而有时候st不通过的时候,你就要看下你配置文件的客户端地址和你访问的是不是一致的,如果不一致也是会报错的。因为cas的验证流程是这样的:他先会给这个url颁发一个st(这里是url),然后验证的时候通过的条件是(这个url并且是这个st,这两者必须相同,如果派发给你的st给的url是localhost,而你去验证的url是127.0.0.1,这样就会报错)。
到这里为止我们已经完成了java客户端整合cas的操作