google浏览器高本版 新增cookie安全机制 不好使了!!!
pom
<!--CAS Client-->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.5.1</version>
</dependency>
application.yml
# 应用名称
spring:
application:
name=vue-cas-client: vue-cas-client
server:
port: 8012
cas:
enable: true
#后端服务地址(回调地址)
client-host-url: http://192.168.0.113:8012/
#cas认证中心地址
server-url-prefix: http://192.168.0.113:8089/cas
#cas认证中心登录地址
server-login-url: http://192.168.0.113:8089/cas/login
#cas不拦截
ignore-pattern: (/file/*)|(/js)|(/test/*)
CasConfig
package com.example.vuecasclient.config;
import com.example.vuecasclient.filter.MyAuthenticationFilter;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.util.AssertionThreadLocalFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class CasConfig {
@Autowired
private CasProperties casProperties;
public CasConfig() {
}
@Bean
public CasProperties getCasProperties()
{
return new CasProperties();
}
@Bean
public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> listener = new ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>();
listener.setEnabled(casProperties.getEnable());
listener.setListener(new SingleSignOutHttpSessionListener());
listener.setOrder(1);
return listener;
}
/**
* 该过滤器用于实现单点登出功能,单点退出配置,一定要放在其他filter之前
*
* @return
*/
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new SingleSignOutFilter());
filterRegistration.setEnabled(casProperties.getEnable());
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", casProperties.getServerUrlPrefix());
filterRegistration.setOrder(3);
return filterRegistration;
}
/**
* 该过滤器负责用户的认证工作
*
* @return
*/
@Bean
public FilterRegistrationBean authenticationFilter() {
FilterRegistrationBean authenticationFilter = new FilterRegistrationBean();
authenticationFilter.setFilter(new MyAuthenticationFilter());
authenticationFilter.addUrlPatterns("/*");
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("ignorePattern", casProperties.getIgnorePattern());
initParameters.put("casServerLoginUrl", casProperties.getServerLoginUrl());
initParameters.put("serverName", casProperties.getClientHostUrl());
authenticationFilter.setInitParameters(initParameters);
authenticationFilter.setOrder(2);
List<String> urlPatterns = new ArrayList<String>();
// 设置匹配的url
authenticationFilter.setUrlPatterns(urlPatterns);
return authenticationFilter;
}
/**
* 该过滤器负责对Ticket的校验工作,使用CAS 3.0协议
*
* @return
*/
@Bean
public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
filterRegistration.setEnabled(casProperties.getEnable());
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", casProperties.getServerUrlPrefix());
filterRegistration.addInitParameter("serverName", casProperties.getClientHostUrl());
filterRegistration.setOrder(5);
return filterRegistration;
}
/**
* request wraper过滤器
* @return
*/
@Bean
public FilterRegistrationBean httpServletRequestWrapperFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(6);
return filterRegistration;
}
/**
* 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
* 比如AssertionHolder.getAssertion().getPrincipal().getName()。
* 这个类把Assertion信息放在ThreadLocal变量中,这样应用程序不在web层也能够获取到当前登录信息
*
* @return
*/
@Bean
public FilterRegistrationBean assertionThreadLocalFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new AssertionThreadLocalFilter());
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(7);
return filterRegistration;
}
}
CasProperties
package com.example.vuecasclient.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="cas")
public class CasProperties {
private Boolean enable;
private String clientHostUrl;
private String serverUrlPrefix;
private String serverLoginUrl;
private String ignorePattern;
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getClientHostUrl() {
return clientHostUrl;
}
public void setClientHostUrl(String clientHostUrl) {
this.clientHostUrl = clientHostUrl;
}
public String getServerUrlPrefix() {
return serverUrlPrefix;
}
public void setServerUrlPrefix(String serverUrlPrefix) {
this.serverUrlPrefix = serverUrlPrefix;
}
public String getServerLoginUrl() {
return serverLoginUrl;
}
public void setServerLoginUrl(String serverLoginUrl) {
this.serverLoginUrl = serverLoginUrl;
}
public String getIgnorePattern() {
return ignorePattern;
}
public void setIgnorePattern(String ignorePattern) {
this.ignorePattern = ignorePattern;
}
}
CorsConfig
package com.example.vuecasclient.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig
{
@Bean
public FilterRegistrationBean corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(Boolean.valueOf(true));
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source), new ServletRegistrationBean[0]);
bean.setOrder(0);
return bean;
}
}
LoginController
package com.example.vuecasclient.controller;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
@Controller
public class LoginController {
@Autowired
private HttpServletRequest request;
@Value("${cas.server-url-prefix}")
private String casServerUrlPrefix;
@RequestMapping({"/getUserInfo"})
@ResponseBody
public Object getUserInfo() {
Map<String, Object> userApi = new HashMap();
Assertion assertion = (Assertion) this.request.getSession().getAttribute("_const_cas_assertion_");
if (assertion != null) {
String loginName = assertion.getPrincipal().getName();
Principal principal = (AttributePrincipal) this.request.getUserPrincipal();
String id = this.request.getSession().getId();
System.out.println("JSESSIONID: "+id);
if ((this.request.getUserPrincipal() != null) &&
((principal instanceof AttributePrincipal))) {
Map<String, Object> result = ((AttributePrincipal) principal).getAttributes();
userApi.put("loginName", loginName);
userApi.put("sex", result.get("sex"));
userApi.put("userName", result.get("userName"));
userApi.put("telephone", result.get("telephone"));
userApi.put("remark", result.get("remark"));
userApi.put("JSESSIONID",id);
}
}
return userApi;
}
@RequestMapping(value = {"/redirect"}, produces = {"text/plain;charset=UTF-8"})
public String redirect(String url,HttpSession session) {
String sessionId = session.getId();
return "redirect:" + url;
}
@RequestMapping({"/loginout"})
public String loginout(String url, HttpSession session) {
session.invalidate();
return "redirect:" + casServerUrlPrefix + "/logout?service=" + url;
}
@RequestMapping(value = {"/test"})
@ResponseBody
public String test(HttpSession session) {
System.out.println("test......");
return "test";
}
}
MyAuthenticationFilter
// An highlighted block
package com.example.vuecasclient.filter;
import com.example.vuecasclient.config.CasProperties;
import com.example.vuecasclient.utils.SpringUtil;
import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.client.Protocol;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.jasig.cas.client.authentication.*;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.stereotype.Component;
@Component
public class MyAuthenticationFilter extends AbstractCasFilter {
private String casServerLoginUrl;
private boolean renew = false;
private boolean gateway = false;
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
private AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;
private static final Map<String, Class<? extends UrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES =
new HashMap<String, Class<? extends UrlPatternMatcherStrategy>>();
static {
PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);
}
public MyAuthenticationFilter() {
this(Protocol.CAS2);
}
protected MyAuthenticationFilter(final Protocol protocol) {
super(protocol);
}
@Override
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
if (!isIgnoreInitConfiguration()) {
super.initInternal(filterConfig);
String loginUrl = getString(ConfigurationKeys.CAS_SERVER_LOGIN_URL);
if (loginUrl != null) {
setCasServerLoginUrl(loginUrl);
} else {
setCasServerUrlPrefix(getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX));
}
setRenew(getBoolean(ConfigurationKeys.RENEW));
setGateway(getBoolean(ConfigurationKeys.GATEWAY));
final String ignorePattern = getString(ConfigurationKeys.IGNORE_PATTERN);
final String ignoreUrlPatternType = getString(ConfigurationKeys.IGNORE_URL_PATTERN_TYPE);
if (ignorePattern != null) {
final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
if (ignoreUrlMatcherClass != null) {
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlMatcherClass.getName());
} else {
try {
logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlPatternType);
} catch (final IllegalArgumentException e) {
logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, e);
}
}
if (this.ignoreUrlPatternMatcherStrategyClass != null) {
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
}
}
final Class<? extends GatewayResolver> gatewayStorageClass = getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);
if (gatewayStorageClass != null) {
setGatewayStorage(ReflectUtils.newInstance(gatewayStorageClass));
}
final Class<? extends AuthenticationRedirectStrategy> authenticationRedirectStrategyClass = getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);
if (authenticationRedirectStrategyClass != null) {
this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
}
}
}
@Override
public void init() {
super.init();
String message = String.format(
"one of %s and %s must not be null.",
ConfigurationKeys.CAS_SERVER_LOGIN_URL.getName(),
ConfigurationKeys.CAS_SERVER_URL_PREFIX.getName());
CommonUtils.assertNotNull(this.casServerLoginUrl, message);
}
@Override
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
String id = request.getSession().getId();
System.out.println("Authentication id "+id);
// response.setHeader("Set-Cookie", "JSESSIONID="+id+";SameSite=None;Secure");
if (isRequestUrlExcluded(request)) {
logger.debug("Request is ignored.");
filterChain.doFilter(request, response);
return;
}
final HttpSession session = request.getSession(false);
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
if (assertion != null) {
filterChain.doFilter(request, response);
return;
}
final String serviceUrl = constructServiceUrl(request, response);
final String ticket = retrieveTicketFromRequest(request);
final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
filterChain.doFilter(request, response);
return;
}
final String modifiedServiceUrl;
logger.debug("no ticket and no assertion found");
if (this.gateway) {
logger.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
logger.debug("Constructed service url: {}", modifiedServiceUrl);
String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
this.logger.debug("redirecting to \"{}\"", urlToRedirectTo);
CasProperties prop = (CasProperties) SpringUtil.getBean("casProperties");
String subUrl = StringUtils.substringBefore(urlToRedirectTo, "service=");
String redirectUrl = subUrl + "service=" + prop.getClientHostUrl() + "redirect?url=";
response.setStatus(403);
response.setHeader("Access-Control-Expose-Headers", "TOKEN_URL");
response.setHeader("TOKEN_URL", redirectUrl);
// String xRequested = request.getHeader("x-requested-with");
// if ("XMLHttpRequest".equals(xRequested)) {
// String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
// getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
//
// this.logger.debug("redirecting to \"{}\"", urlToRedirectTo);
// CasProperties prop = (CasProperties) SpringUtil.getBean("casProperties");
// String subUrl = StringUtils.substringBefore(urlToRedirectTo, "service=");
// String redirectUrl = subUrl + "service=" + prop.getClientHostUrl() + "redirect?url=";
// response.setStatus(403);
// response.setHeader("Access-Control-Expose-Headers", "TOKEN_URL");
// response.setHeader("TOKEN_URL", redirectUrl);
// } else {
// final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
// getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
//
// logger.debug("redirecting to \"{}\"", urlToRedirectTo);
// this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
// }
}
public final void setRenew(final boolean renew) {
this.renew = renew;
}
public final void setGateway(final boolean gateway) {
this.gateway = gateway;
}
public final void setCasServerUrlPrefix(final String casServerUrlPrefix) {
setCasServerLoginUrl(CommonUtils.addTrailingSlash(casServerUrlPrefix) + "login");
}
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
this.gatewayStorage = gatewayStorage;
}
private boolean isRequestUrlExcluded(final HttpServletRequest request) {
if (this.ignoreUrlPatternMatcherStrategyClass == null) {
return false;
}
final StringBuffer urlBuffer = request.getRequestURL();
if (request.getQueryString() != null) {
urlBuffer.append("?").append(request.getQueryString());
}
final String requestUri = urlBuffer.toString();
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
}
public final void setIgnoreUrlPatternMatcherStrategyClass(
final UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass) {
this.ignoreUrlPatternMatcherStrategyClass = ignoreUrlPatternMatcherStrategyClass;
}
}
前端
sso-login.js
/*
* @Descripttion:
* @Author: jibl
* @Date: 2022-06-16 17:07:21
* @LastEditors: jibl
* @LastEditTime: 2022-10-12 15:19:46
*/
'use strict'
import axios from 'axios'
axios.defaults.withCredentials = true
axios.defaults.crossDomain = true
axios.interceptors.response.use(
response => {
return response;
},
error => {
// && response.config.url !== 'http://192.168.0.30:7003/polymerization/getMsgErrorLst'
const response = error.response
if (response && response.status === 403) {
window.location.href = response.headers['token_url'] + window.location.href
}
})
;
main.js引入sso-login.js后测试:
<el-button @click="postRequest" type="primary">发送请求</el-button>
postRequest() {
axios({
method: "get",
url: "http://192.168.0.113:8012/getUserInfo",
params: {},
headers: {
"Content-Type": "application/json; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
})
.then((res) => {
console.log("userinfo.......", res)
})
.catch((err) => {
console.log(err);
});