com.gframework.boot.mvc.config.CasConfig Maven / Gradle / Ivy
The newest version!
package com.gframework.boot.mvc.config;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import org.jasig.cas.client.Protocol;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.AssertionHolder;
import org.jasig.cas.client.validation.AbstractTicketValidationFilter;
import org.jasig.cas.client.validation.Assertion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
import com.gframework.annotation.EnableCasClientSecurity;
import com.gframework.autoconfigure.mvc.cas.CasExtendConfigurationProperties;
import com.gframework.boot.mvc.controller.session.cas.CasSessionUserCreateFilter;
import net.unicon.cas.client.configuration.CasClientConfiguration;
import net.unicon.cas.client.configuration.CasClientConfigurerAdapter;
/**
* 单点登录相关配置.
* 本类由 {@link EnableCasClientSecurity} 注解进行启动
*
* CAS核心的逻辑处理过滤器是:
*
重定向控制:{@link AuthenticationFilter}
* ticket验证:{@link AbstractTicketValidationFilter}抽象类的相关子类(根据cas协议号的不同,子类不同)
*
* @since 1.0.0
* @author Ghwolf
*/
@SuppressWarnings("rawtypes")
@EnableConfigurationProperties(CasExtendConfigurationProperties.class)
@ConditionalOnClass({Assertion.class,AbstractCasFilter.class,AssertionHolder.class})
public class CasConfig extends CasClientConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(CasConfig.class);
/**
* cas 非标准额外配置信息
*/
@Autowired
private CasExtendConfigurationProperties casConfiguration;
/**
* 允许post提交ticket的代理类
* @author Ghwolf
*/
class RetrieveTicketFromRequestCallback implements MethodInterceptor {
static final String INTERCEPTOR_METHOD_NAME = "retrieveTicketFromRequest";
private String paramName ;
RetrieveTicketFromRequestCallback(AbstractCasFilter f){
Field protocol;
try {
protocol = AbstractCasFilter.class.getDeclaredField("protocol");
protocol.setAccessible(true);
Protocol p = (Protocol) protocol.get(f);
this.paramName = p.getArtifactParameterName();
} catch (Exception e) {
logger.error("获取 AbstractCasFilter 类的protocol属性失败,请检查CAS版本以及是否存在安全管理器。");
throw new UnsupportedOperationException(e);
}
}
@Override
public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy proxyMethod) throws Throwable {
HttpServletRequest request = (HttpServletRequest) args[0] ;
return request.getParameter(paramName);
}
}
/**
* 传一个基本的AbstractCasFilter类对象,然后将其转换为支持POST传ticket的过滤器
*/
private AbstractCasFilter createAllowPostTicketFilter(AbstractCasFilter filter) {
// cas 的三个协议操作类都是public且可继承的,因此这里可以直接用getClass()
Enhancer en = new Enhancer();
en.setSuperclass(filter.getClass());
en.setCallbacks(new Callback[]{
NoOp.INSTANCE,
new RetrieveTicketFromRequestCallback(filter)
});
en.setCallbackFilter(m -> RetrieveTicketFromRequestCallback.INTERCEPTOR_METHOD_NAME.equals(m.getName()) ? 1 : 0);
return (AbstractCasFilter) en.create();
}
/**
* 这个bean的创建代码在{@link CasClientConfiguration}类的100行左右,基本都是无参构造
*/
@SuppressWarnings("unchecked")
@Override
public void configureValidationFilter(FilterRegistrationBean validationFilter) {
validationFilter.setOrder(1);
if (casConfiguration.isAllowPostTicket()) {
Filter filter = validationFilter.getFilter();
if (filter instanceof AbstractCasFilter) {
filter = createAllowPostTicketFilter((AbstractCasFilter)filter);
validationFilter.setFilter(filter);
if (logger.isInfoEnabled()) {
logger.info("cas被修改为支持获取post方式提交的ticket参数!");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn(
"cas被修改为支持获取post方式提交的ticket参数,但是目前使用的cas版本的ValidationFilter不是AbstractCasFilter的子类,目前是:{}",
filter == null ? "null" : filter.getClass());
}
}
}
super.configureValidationFilter(validationFilter);
}
@Override
public void configureAuthenticationFilter(FilterRegistrationBean authenticationFilter) {
authenticationFilter.setOrder(2);
// url过滤
if (!StringUtils.isEmpty(this.casConfiguration.getIgnorePattern())) {
authenticationFilter.addInitParameter(ConfigurationKeys.IGNORE_PATTERN.getName(),
this.casConfiguration.getIgnorePattern());
}
super.configureAuthenticationFilter(authenticationFilter);
}
/**
* 此过滤器在AuthenticationFilter之后,目的是将cas自己的用户认证信息进行替换,但是原始功能保留。
*/
@Bean
public FilterRegistrationBean configureSessionUserFilter(CasSessionUserCreateFilter casSessionUserCreateFilter) {
FilterRegistrationBean filterBean = new FilterRegistrationBean<>(casSessionUserCreateFilter);
filterBean.setOrder(3);
return filterBean;
}
/**
* 更改顺序+1
*/
@Override
public void configureHttpServletRequestWrapperFilter(FilterRegistrationBean httpServletRequestWrapperFilter) {
httpServletRequestWrapperFilter.setOrder(4);
super.configureHttpServletRequestWrapperFilter(httpServletRequestWrapperFilter);
}
/**
* 更改顺序+1
*/
@Override
public void configureAssertionThreadLocalFilter(FilterRegistrationBean assertionThreadLocalFilter) {
// XXX 这里只是存储一个threadlocal,看是否用到,没有就去掉
assertionThreadLocalFilter.setOrder(5);
super.configureAssertionThreadLocalFilter(assertionThreadLocalFilter);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy