packageorg.jasig.cas.client.authentication;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.jasig.cas.client.util.AbstractCasFilter;
importorg.jasig.cas.client.util.CommonUtils;
importorg.jasig.cas.client.util.ReflectUtils;
importorg.jasig.cas.client.validation.Assertion;
import org.slf4j.Logger;
public class AuthenticationFilter
extends AbstractCasFilter
{
//sso中心认证服务的登录地址。
private String casServerLoginUrl;
private boolean renew = false;
private boolean gateway = false;
//网关存储解析器。
private GatewayResolver gatewayStorage = newDefaultGatewayResolverImpl();
//认证重定向策略,默认是直接重定向地址。
private AuthenticationRedirectStrategy authenticationRedirectStrategy =new DefaultAuthenticationRedirectStrategy();
//可以被忽略的url模式匹配策略。
private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass =null;
private static final Map<String, Class<? extendsUrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES = new HashMap();
//默认有3种模式匹配策略:包含、正则、相等。
static
{
PATTERN_MATCHER_TYPES.put("CONTAINS",ContainsPatternUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("REGEX",RegexUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("EXACT",ExactUrlPatternMatcherStrategy.class);
}
protected void initInternal(FilterConfig filterConfig)
throws ServletException
{
if (!isIgnoreInitConfiguration())
{
super.initInternal(filterConfig);
setCasServerLoginUrl(getPropertyFromInitParams(filterConfig,"casServerLoginUrl", null));
this.logger.trace("Loaded CasServerLoginUrl parameter: {}",this.casServerLoginUrl);
setRenew(parseBoolean(getPropertyFromInitParams(filterConfig,"renew", "false")));
this.logger.trace("Loaded renew parameter: {}",Boolean.valueOf(this.renew));
setGateway(parseBoolean(getPropertyFromInitParams(filterConfig,"gateway", "false")));
this.logger.trace("Loaded gateway parameter: {}",Boolean.valueOf(this.gateway));
//忽略模式:可以自定义、根据实际情况配置,默认是正则表达式。
String ignorePattern = getPropertyFromInitParams(filterConfig,"ignorePattern", null);
this.logger.trace("Loaded ignorePattern parameter: {}",ignorePattern);
//默认是正则模式,可以自定义实现UrlPatternMatcherStrategy接口。
String ignoreUrlPatternType = getPropertyFromInitParams(filterConfig,"ignoreUrlPatternType", "REGEX");
this.logger.trace("Loaded ignoreUrlPatternType parameter: {}",ignoreUrlPatternType);
if (ignorePattern != null)
{
Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass =(Class)PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
if (ignoreUrlMatcherClass != null) {
this.ignoreUrlPatternMatcherStrategyClass = ((UrlPatternMatcherStrategy)ReflectUtils.newInstance(ignoreUrlMatcherClass.getName(),new Object[0]));
} else {
try
{
this.logger.trace("Assuming {} is a qualified class name...",ignoreUrlPatternType);
this.ignoreUrlPatternMatcherStrategyClass =((UrlPatternMatcherStrategy)ReflectUtils.newInstance(ignoreUrlPatternType, newObject[0]));
}
catch (IllegalArgumentException e)
{
this.logger.error("Could not instantiate class [{}]",ignoreUrlPatternType, e);
}
}
if (this.ignoreUrlPatternMatcherStrategyClass != null) {
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
}
}
String gatewayStorageClass = getPropertyFromInitParams(filterConfig,"gatewayStorageClass", null);
if (gatewayStorageClass != null) {
this.gatewayStorage =((GatewayResolver)ReflectUtils.newInstance(gatewayStorageClass, newObject[0]));
}
String authenticationRedirectStrategyClass =getPropertyFromInitParams(filterConfig,"authenticationRedirectStrategyClass", null);
if (authenticationRedirectStrategyClass != null) {
this.authenticationRedirectStrategy =((AuthenticationRedirectStrategy)ReflectUtils.newInstance(authenticationRedirectStrategyClass,new Object[0]));
}
}
}
public void init()
{
super.init();
CommonUtils.assertNotNull(this.casServerLoginUrl,"casServerLoginUrl cannot be null.");
}
public final void doFilter(ServletRequest servletRequest,ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
//判断当前请求url是否可以被忽略模式匹配认证通过。
if (isRequestUrlExcluded(request))
{
this.logger.debug("Request is ignored.");
filterChain.doFilter(request, response);
return;
}
//获取sso认证中心存储的session属性_const_cas_assertion_。
HttpSession session = request.getSession(false);
Assertion assertion = session != null ?(Assertion)session.getAttribute("_const_cas_assertion_") : null;
if (assertion != null)
{
filterChain.doFilter(request, response);
return;
}
//从request中构建需要认证的服务url。
String serviceUrl = constructServiceUrl(request, response);
//从request中获取票据ticket。
String ticket = retrieveTicketFromRequest(request);
//如果设置网关,则从session当中获取属性_const_cas_gateway,并从session中去掉此属性。
boolean wasGatewayed = (this.gateway) &&(this.gatewayStorage.hasGatewayedAlready(request, serviceUrl));
//如果存在认证票据ticket或者网关设置,则直接认证通过。
if ((CommonUtils.isNotBlank(ticket)) || (wasGatewayed))
{
filterChain.doFilter(request, response);
return;
}
this.logger.debug("no ticket and no assertion found");
String modifiedServiceUrl;
if (this.gateway)
{
this.logger.debug("setting gateway attribute in session");
//在session中设置网关属性_const_cas_gateway=yes
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request,serviceUrl);
}
else
{
modifiedServiceUrl = serviceUrl;
}
this.logger.debug("Constructed service url: {}",modifiedServiceUrl);
//直接重定向sso认证中心url,进行登录认证。
String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
this.logger.debug("redirecting to \"{}\"",urlToRedirectTo);
this.authenticationRedirectStrategy.redirect(request, response,urlToRedirectTo);
}
public final void setRenew(boolean renew)
{
this.renew = renew;
}
public final void setGateway(boolean gateway)
{
this.gateway = gateway;
}
public final void setCasServerLoginUrl(String casServerLoginUrl)
{
this.casServerLoginUrl = casServerLoginUrl;
}
public final void setGatewayStorage(GatewayResolver gatewayStorage)
{
this.gatewayStorage = gatewayStorage;
}
//根据可以忽略的URL地址匹配策略,来判断当前请求url是否可以认证:因此在配置此过滤器的时候,如果存在不需要认证的url,那么就可以根据url的形式配置ignorePattern参数和ignoreUrlPatternType参数。
private boolean isRequestUrlExcluded(HttpServletRequest request)
{
if (this.ignoreUrlPatternMatcherStrategyClass == null) {
return false;
}
StringBuffer urlBuffer = request.getRequestURL();
if (request.getQueryString() != null) {
urlBuffer.append("?").append(request.getQueryString());
}
String requestUri = urlBuffer.toString();
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
}
}