springboot集成统一认证服务
- 配置文件配置属性
# 统一认证登录
# cas服务地址
cas.loginServer=https://xxx.xxx.xxx/cas
#cas服务端的登录地址
cas.validateServer=https://xxx.xxx.xxx/cas
#当前服务器的地址(客户端)
cas.serverName=当前服务地址
- 配置类
(1)配置类1
import org.jasig.cas.client.authentication.DefaultGatewayResolverImpl;
import org.jasig.cas.client.authentication.GatewayResolver;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Administrator
*/
@Order(3)
@Component
@WebFilter(filterName = "AuthenticationFilter", urlPatterns = "/*", initParams = {})
public class AuthenticationFilter extends AbstractCasFilter {
@Value("${cas.serverName}")
private String serverName ;
@Value("${cas.loginServer}")
private String loginServer ;
private String[] excludePaths = {"/platLogin.htm"};
public String[] getExcludePaths() {
return excludePaths;
}
public void setExcludePaths(String[] excludePaths) {
this.excludePaths = excludePaths;
}
private boolean renew = false;
private boolean gateway = false;
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
private String port;
public String getServerUrl() {
return "http://"+serverName;
}
public String getLoginServerUrl(){
return loginServer;
}
@Override
protected void initInternal(FilterConfig filterConfig) throws ServletException {
if (!isIgnoreInitConfiguration()) {
super.initInternal(filterConfig);
setCasServerLoginUrl(getLoginServerUrl()+"/login");
if((getServerUrl())!=null){
super.setServerName((getServerUrl()));
}
final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);
if (gatewayStorageClass != null) {
try {
this.gatewayStorage = (GatewayResolver) Class.forName(gatewayStorageClass).newInstance();
} catch (final Exception e) {
log.error(e,e);
throw new ServletException(e);
}
}
//拦截器过滤修改************begin*************************
String _excludePaths = getPropertyFromInitParams(filterConfig, "excepPaths", null);
if(CommonUtils.isNotBlank(_excludePaths)){
setExcludePaths(_excludePaths.trim().split(","));
}
//拦截器过滤修改************end************************
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
final HttpSession session = request.getSession(false);
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
//拦截器过滤修改************begin********************
String uri = request.getRequestURI();
boolean isInWhiteList = true;
if(excludePaths!=null && excludePaths.length>0 && uri!=null){
if (Arrays.asList(excludePaths).contains(uri)){
isInWhiteList = false;
}
}
if(isInWhiteList){
filterChain.doFilter(request, response);
return;
}
//拦截器过滤修改************end********************************
if (assertion != null) {
filterChain.doFilter(request, response);
return;
}
final String serviceUrl = constructServiceUrl(request, response);
final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());
final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
filterChain.doFilter(request, response);
return;
}
final String modifiedServiceUrl;
log.debug("no ticket and no assertion found");
if (this.gateway) {
log.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
if (log.isDebugEnabled()) {
log.debug("Constructed service url: " + modifiedServiceUrl);
}
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
if (log.isDebugEnabled()) {
log.debug("redirecting to \"" + urlToRedirectTo + "\"");
}
response.sendRedirect(urlToRedirectTo);
}
/**
* The URL to the CAS Server login.
*/
private String casServerLoginUrl;
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
this.gatewayStorage = gatewayStorage;
}
}
(2)配置类2
import org.jasig.cas.client.proxy.*;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
@Order(4)
@Component
@WebFilter(filterName = "Cas20ProxyReceivingTicketValidationFilter", urlPatterns = "/*")
public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketValidationFilter {
@Value("${cas.serverName}")
private String serverName ;
@Value("${cas.validateServer}")
private String validateServer ;
private static final String[] RESERVED_INIT_PARAMS = new String[] {"proxyGrantingTicketStorageClass", "proxyReceptorUrl", "acceptAnyProxy", "allowedProxyChains", "casServerUrlPrefix", "proxyCallbackUrl", "renew", "exceptionOnValidationFailure", "redirectAfterValidation", "useSession", "service", "artifactParameterName", "serviceParameterName", "encodeServiceUrl", "millisBetweenCleanUps", "hostnameVerifier", "encoding", "config"};
private static final int DEFAULT_MILLIS_BETWEEN_CLEANUPS = 60 * 1000;
/**
* The URL to send to the CAS server as the URL that will process proxying requests on the CAS client.
*/
private String proxyReceptorUrl;
private Timer timer;
private TimerTask timerTask;
private int millisBetweenCleanUps;
private ProxyGrantingTicketStorage proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();
public String getServerUrl() {
return "http://"+serverName;
}
@Override
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
super.setServerName(getServerUrl());
setProxyReceptorUrl(getPropertyFromInitParams(filterConfig, "proxyReceptorUrl", null));
final String proxyGrantingTicketStorageClass = getPropertyFromInitParams(filterConfig, "proxyGrantingTicketStorageClass", null);
if (proxyGrantingTicketStorageClass != null) {
this.proxyGrantingTicketStorage = ReflectUtils.newInstance(proxyGrantingTicketStorageClass);
if (this.proxyGrantingTicketStorage instanceof AbstractEncryptedProxyGrantingTicketStorageImpl) {
final AbstractEncryptedProxyGrantingTicketStorageImpl p = (AbstractEncryptedProxyGrantingTicketStorageImpl) this.proxyGrantingTicketStorage;
final String cipherAlgorithm = getPropertyFromInitParams(filterConfig, "cipherAlgorithm", AbstractEncryptedProxyGrantingTicketStorageImpl.DEFAULT_ENCRYPTION_ALGORITHM);
final String secretKey = getPropertyFromInitParams(filterConfig, "secretKey", null);
p.setCipherAlgorithm(cipherAlgorithm);
try {
if (secretKey != null) {
p.setSecretKey(secretKey);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
log.trace("Setting proxyReceptorUrl parameter: " + this.proxyReceptorUrl);
this.millisBetweenCleanUps = Integer.parseInt(getPropertyFromInitParams(filterConfig, "millisBetweenCleanUps", Integer.toString(DEFAULT_MILLIS_BETWEEN_CLEANUPS)));
super.initInternal(filterConfig);
}
// @Override
public void init() {
super.init();
CommonUtils.assertNotNull(this.proxyGrantingTicketStorage, "proxyGrantingTicketStorage cannot be null.");
if (this.timer == null) {
this.timer = new Timer(true);
}
if (this.timerTask == null) {
this.timerTask = new CleanUpTimerTask(this.proxyGrantingTicketStorage);
}
this.timer.schedule(this.timerTask, this.millisBetweenCleanUps, this.millisBetweenCleanUps);
}
/**
* Constructs a Cas20ServiceTicketValidator or a Cas20ProxyTicketValidator based on supplied parameters.
*
* @param filterConfig the Filter Configuration object.
* @return a fully constructed TicketValidator.
*/
@Override
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
final String allowAnyProxy = getPropertyFromInitParams(filterConfig, "acceptAnyProxy", null);
final String allowedProxyChains = getPropertyFromInitParams(filterConfig, "allowedProxyChains", null);
final String casServerUrlPrefix = "https://xxx.xxx.xxx/cas" ;
final Cas20ServiceTicketValidator validator;
if (CommonUtils.isNotBlank(allowAnyProxy) || CommonUtils.isNotBlank(allowedProxyChains)) {
final Cas20ProxyTicketValidator v = new Cas20ProxyTicketValidator(casServerUrlPrefix);
v.setAcceptAnyProxy(parseBoolean(allowAnyProxy));
v.setAllowedProxyChains(CommonUtils.createProxyList(allowedProxyChains));
validator = v;
} else {
validator = new Cas20ServiceTicketValidator(casServerUrlPrefix);
}
validator.setProxyCallbackUrl(getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", null));
validator.setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage);
validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig, "encoding", null)));
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", "UTF-8"));
final Map<String,String> additionalParameters = new HashMap<String,String>();
final List<String> params = Arrays.asList(RESERVED_INIT_PARAMS);
for (final Enumeration<?> e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
final String s = (String) e.nextElement();
if (!params.contains(s)) {
additionalParameters.put(s, filterConfig.getInitParameter(s));
}
}
validator.setCustomParameters(additionalParameters);
validator.setHostnameVerifier(getHostnameVerifier(filterConfig));
return validator;
}
@Override
public void destroy() {
super.destroy();
this.timer.cancel();
}
/**
* This processes the ProxyReceptor request before the ticket validation code executes.
*/
@Override
protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String requestUri = request.getRequestURI();
if (CommonUtils.isEmpty(this.proxyReceptorUrl) || !requestUri.endsWith(this.proxyReceptorUrl)) {
return true;
}
try {
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
} catch (final RuntimeException e) {
log.error(e.getMessage(), e);
throw e;
}
return false;
}
public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
this.proxyReceptorUrl = proxyReceptorUrl;
}
public void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage storage) {
this.proxyGrantingTicketStorage = storage;
}
public void setTimer(final Timer timer) {
this.timer = timer;
}
public void setTimerTask(final TimerTask timerTask) {
this.timerTask = timerTask;
}
public void setMillisBetweenCleanUps(final int millisBetweenCleanUps) {
this.millisBetweenCleanUps = millisBetweenCleanUps;
}
@Override
protected void onSuccessfulValidation(HttpServletRequest request, HttpServletResponse response,
Assertion assertion) {
}
}
/platLogin.htm
,是点击登录后跳转的页面
getTicketValidator
方法中的casServerUrlPrefix
这个参数需要直接赋值,不然会启动不成功
3. 控制器获取数据
@PostMapping("/valid")
public void valid(HttpServletRequest request) {
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
if (assertion != null) {
AttributePrincipal principal = assertion.getPrincipal();
System.out.println("princial:" + principal);
System.out.println(principal.getName());
for (Map.Entry<String, Object> e : principal.getAttributes().entrySet()) {
System.out.println("数据:----"+e.getKey() + ":" + e.getValue() + "(" + e.getValue().getClass() + ")");
}
}
// 根据需求来做,向数据库中添加对应数据后,可直接登录,返回token
}
- 页面
platLogin.htm
<!DOCTYPE html>
<html>
<head>
<script src="${res}/js/jquery-1.12.4.js" type="text/javascript" charset="utf-8"></script>
<script>
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
function platLogin() {
var obj = {target:"member"};
$.ajax({
type: "POST",
url: "/xxx/xxx",
data: obj,
success: function (result) {
if (result.code == 200) {
if(result.data['token']){
localStorage.setItem('token', result.data['token']);
var localredirect = getQueryVariable("redirect");
if( localredirect)
{
location.href = localredirect
return
}
if(result.redirectUrl){
location.href = result.redirectUrl
}else{
location.href = '/';
}
}
}
}
});
}
platLogin();
</script>
</head>
<body>
</body>
</html>