diff --git a/integrations/spring-security-cas-demo/pom.xml b/integrations/spring-security-cas-demo/pom.xml
new file mode 100644
index 00000000..4c9d9f7b
--- /dev/null
+++ b/integrations/spring-security-cas-demo/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+ com.unicom.sso
+ sso-springboot-sample
+ 0.0.1-SNAPSHOT
+
+
+ sso-bigdata-cas-starter-demo
+ cas 单点登录demo
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.security
+ spring-security-cas
+
+
+
+
\ No newline at end of file
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/CasApplication.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/CasApplication.java
new file mode 100644
index 00000000..aa0b81ae
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/CasApplication.java
@@ -0,0 +1,17 @@
+package com.unicom.sso.bigdata.cas.demo;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+/**
+ * cas 单点
+ * @author baihz10
+ * @date 2023/7/7 15:18
+ */
+//@EnableCasClient
+@SpringBootApplication
+public class CasApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(CasApplication.class, args);
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/AuthorityInfo.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/AuthorityInfo.java
new file mode 100644
index 00000000..60608e80
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/AuthorityInfo.java
@@ -0,0 +1,25 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import org.springframework.security.core.GrantedAuthority;
+
+public class AuthorityInfo implements GrantedAuthority {
+ private static final long serialVersionUID = -175781100474818800L;
+
+ /**
+ * 权限CODE
+ */
+ private String authority;
+
+ public AuthorityInfo(String authority) {
+ this.authority = authority;
+ }
+
+ @Override
+ public String getAuthority() {
+ return authority;
+ }
+
+ public void setAuthority(String authority) {
+ this.authority = authority;
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasConfig.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasConfig.java
new file mode 100644
index 00000000..067150ef
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasConfig.java
@@ -0,0 +1,120 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import org.jasig.cas.client.session.SingleSignOutFilter;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.jasig.cas.client.validation.Cas30ProxyTicketValidator;
+import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidator;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.cas.ServiceProperties;
+import org.springframework.security.cas.authentication.CasAuthenticationProvider;
+import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
+import org.springframework.security.cas.web.CasAuthenticationFilter;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Configuration
+public class CasConfig {
+
+ @Value("${cas.server.url}")
+ private String casServerUrl;
+ @Value("${base.url}")
+ private String baseUrl;
+
+ @Bean
+ public AuthenticationEntryPoint authenticationEntryPoint() {
+ CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
+ entryPoint.setLoginUrl(casServerUrl + "/login");
+ entryPoint.setServiceProperties(this.serviceProperties());
+ return entryPoint;
+ }
+
+ @Bean
+ protected AuthenticationManager authenticationManager() throws Exception {
+ return new ProviderManager(this.casAuthenticationProvider());
+ }
+
+ @Bean
+ public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
+ CasAuthenticationFilter filter = new CasAuthenticationFilter();
+ filter.setAuthenticationManager(this.authenticationManager());
+ filter.setServiceProperties(this.serviceProperties());
+ filter.setAuthenticationFailureHandler(this.authenticationFailureHandler());
+ filter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler());
+ return filter;
+ }
+
+ @Bean
+ public AuthenticationSuccessHandler authenticationSuccessHandler() {
+ AuthenticationSuccessHandler authenticationSuccessHandler = new SimpleUrlAuthenticationSuccessHandler();
+
+ return authenticationSuccessHandler;
+ }
+
+ @Bean
+ public AuthenticationFailureHandler authenticationFailureHandler() {
+ AuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler();
+
+ return authenticationFailureHandler;
+ }
+
+ @Bean
+ public ServiceProperties serviceProperties() {
+ ServiceProperties serviceProperties = new ServiceProperties();
+ serviceProperties.setService(baseUrl);
+ serviceProperties.setSendRenew(false);
+ return serviceProperties;
+ }
+
+ @Bean
+ public TicketValidator ticketValidator() {
+ return new Cas30ProxyTicketValidator(casServerUrl);
+ }
+
+ @Bean
+ public CasAuthenticationProvider casAuthenticationProvider() {
+ CasAuthenticationProvider provider = new CasAuthenticationProvider();
+ provider.setServiceProperties(this.serviceProperties());
+ provider.setTicketValidator(this.ticketValidator());
+ provider.setAuthenticationUserDetailsService(new UserDetailsServiceImpl());
+ provider.setKey("CAS_PROVIDER_LOCALHOST");
+ return provider;
+ }
+
+ @Bean
+ public SecurityContextLogoutHandler securityContextLogoutHandler() {
+ return new SecurityContextLogoutHandler();
+ }
+
+ @Bean
+ public LogoutFilter logoutFilter() {
+ LogoutFilter logoutFilter = new LogoutFilter(casServerUrl + "/logout?service=" + baseUrl,
+ securityContextLogoutHandler());
+ logoutFilter.setFilterProcessesUrl("/logout/cas");
+ return logoutFilter;
+ }
+
+ @Bean
+ public SingleSignOutFilter singleSignOutFilter() {
+ SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
+ singleSignOutFilter.setIgnoreInitConfiguration(true);
+ return singleSignOutFilter;
+ }
+
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasProperties.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasProperties.java
new file mode 100644
index 00000000..15d486ef
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasProperties.java
@@ -0,0 +1,96 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * CAS的配置参数
+ */
+@Component
+public class CasProperties {
+ @Value("${cas.server.host.url}")
+ private String casServerUrl;
+
+ @Value("${cas.server.host.login_url}")
+ private String casServerLoginUrl;
+
+ @Value("${cas.server.host.logout_url}")
+ private String casServerLogoutUrl;
+
+ @Value("${app.casEnable}")
+ private boolean casEnable;
+
+ @Value("${app.server.host.url}")
+ private String appServerUrl;
+
+ @Value("${app.login_url}")
+ private String appLoginUrl;
+
+ @Value("${app.logout_url}")
+ private String appLogoutUrl;
+
+ @Value("${app.web_url}")
+ private String webUrl;
+
+ public String getWebUrl() {
+ return webUrl;
+ }
+
+ public String getCasServerUrl() {
+ return casServerUrl;
+ }
+
+ public void setCasServerUrl(String casServerUrl) {
+ this.casServerUrl = casServerUrl;
+ }
+
+ public String getCasServerLoginUrl() {
+ return casServerLoginUrl;
+ }
+
+ public void setCasServerLoginUrl(String casServerLoginUrl) {
+ this.casServerLoginUrl = casServerLoginUrl;
+ }
+
+ public String getCasServerLogoutUrl() {
+ return casServerLogoutUrl;
+ }
+
+ public void setCasServerLogoutUrl(String casServerLogoutUrl) {
+ this.casServerLogoutUrl = casServerLogoutUrl;
+ }
+
+ public boolean isCasEnable() {
+ return casEnable;
+ }
+
+ public void setCasEnable(boolean casEnable) {
+ this.casEnable = casEnable;
+ }
+
+ public String getAppServerUrl() {
+ return appServerUrl;
+ }
+
+ public void setAppServerUrl(String appServerUrl) {
+ this.appServerUrl = appServerUrl;
+ }
+
+ public String getAppLoginUrl() {
+ return appLoginUrl;
+ }
+
+ public void setAppLoginUrl(String appLoginUrl) {
+ this.appLoginUrl = appLoginUrl;
+ }
+
+ public String getAppLogoutUrl() {
+ return appLogoutUrl;
+ }
+
+ public void setAppLogoutUrl(String appLogoutUrl) {
+ this.appLogoutUrl = appLogoutUrl;
+ }
+
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CustomUserDetailsService.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CustomUserDetailsService.java
new file mode 100644
index 00000000..d9f848ad
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CustomUserDetailsService.java
@@ -0,0 +1,17 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+public class CustomUserDetailsService implements UserDetailsService {
+
+ @Override
+ public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
+ // 可自定义获取用户信息
+ return new User("admin", "admin", true, true, true, true,
+ AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
+ }
+}
\ No newline at end of file
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/JwtAuthenticationTokenFilter.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/JwtAuthenticationTokenFilter.java
new file mode 100644
index 00000000..3ab2cd74
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/JwtAuthenticationTokenFilter.java
@@ -0,0 +1,37 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
+{
+ @Autowired
+ private TokenService tokenService;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException
+ {
+ LoginUser loginUser = tokenService.getLoginUser(request);
+ if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
+ {
+ tokenService.verifyToken(loginUser);
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+ authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ }
+ chain.doFilter(request, response);
+ }
+}
+
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/LoginUser.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/LoginUser.java
new file mode 100644
index 00000000..8b760f0c
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/LoginUser.java
@@ -0,0 +1,233 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public class LoginUser implements UserDetails
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 用户唯一标识
+ */
+ private String token;
+
+ /**
+ * 登录时间
+ */
+ private Long loginTime;
+
+ /**
+ * 过期时间
+ */
+ private Long expireTime;
+
+ /**
+ * 登录IP地址
+ */
+ private String ipaddr;
+
+ /**
+ * 登录地点
+ */
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ private String os;
+
+ /**
+ * 权限列表
+ */
+ private Set permissions;
+
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+
+ public void setToken(String token)
+ {
+ this.token = token;
+ }
+
+ public LoginUser()
+ {
+ }
+
+
+ /**
+ * 账户是否未过期,过期无法验证
+ */
+ @JsonIgnore
+ @Override
+ public boolean isAccountNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 指定用户是否解锁,锁定的用户无法进行身份验证
+ *
+ * @return
+ */
+ @JsonIgnore
+ @Override
+ public boolean isAccountNonLocked()
+ {
+ return true;
+ }
+
+ /**
+ * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+ *
+ * @return
+ */
+ @JsonIgnore
+ @Override
+ public boolean isCredentialsNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 是否可用 ,禁用的用户不能身份验证
+ *
+ * @return
+ */
+ @JsonIgnore
+ @Override
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public Long getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Long loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Long getExpireTime()
+ {
+ return expireTime;
+ }
+
+ public void setExpireTime(Long expireTime)
+ {
+ this.expireTime = expireTime;
+ }
+
+ public Set getPermissions()
+ {
+ return permissions;
+ }
+
+ public void setPermissions(Set permissions)
+ {
+ this.permissions = permissions;
+ }
+
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities()
+ {
+ return new HashSet();
+ }
+
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public String getUsername() {
+ return null;
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/SecurityConfig.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/SecurityConfig.java
new file mode 100644
index 00000000..d6aad444
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/SecurityConfig.java
@@ -0,0 +1,251 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import org.jasig.cas.client.session.SingleSignOutFilter;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.cas.ServiceProperties;
+import org.springframework.security.cas.authentication.CasAuthenticationProvider;
+import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
+import org.springframework.security.cas.web.CasAuthenticationFilter;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.annotation.Resource;
+
+/**
+ * spring security配置
+ *
+ * @author ruoyi
+ */
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter
+{
+ @Autowired
+ private CasProperties casProperties;
+
+ @Autowired
+ private CasUserDetailsService customUserDetailsService;
+
+ @Autowired
+ private CasAuthenticationSuccessHandler casAuthenticationSuccessHandler;
+
+ /**
+ * 自定义用户认证逻辑
+ */
+ @Autowired
+ private UserDetailsService userDetailsService;
+
+ /**
+ * 认证失败处理类
+ */
+ @Autowired
+ private AuthenticationEntryPointImpl unauthorizedHandler;
+
+ /**
+ * 退出处理类
+ */
+ @Autowired
+ private LogoutSuccessHandlerImpl logoutSuccessHandler;
+
+ /**
+ * token认证过滤器
+ */
+ @Autowired
+ private JwtAuthenticationTokenFilter authenticationTokenFilter;
+
+ /**
+ * 跨域过滤器
+ */
+ @Autowired
+ private CorsFilter corsFilter;
+
+
+ /**
+ * 解决 无法直接注入 AuthenticationManager
+ *
+ * @return
+ * @throws Exception
+ */
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ /**
+ * anyRequest | 匹配所有请求路径
+ * access | SpringEl表达式结果为true时可以访问
+ * anonymous | 匿名可以访问
+ * denyAll | 用户不能访问
+ * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
+ * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
+ * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
+ * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
+ * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
+ * hasRole | 如果有参数,参数表示角色,则其角色可以访问
+ * permitAll | 用户可以任意访问
+ * rememberMe | 允许通过remember-me登录的用户访问
+ * authenticated | 用户登录后可访问
+ */
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ //开启cas
+ if (casProperties.isCasEnable()) {
+ httpSecurity
+ // CSRF禁用,因为不使用session
+ .csrf().disable()
+ // 基于token,所以不需要session
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+ // 过滤请求
+ .authorizeRequests()
+ // 对于登录login 验证码captchaImage 允许匿名访问
+ //.antMatchers("/login", "/captchaImage").anonymous()
+ .antMatchers(
+ HttpMethod.GET,
+ "/*.html",
+ "/**/*.html",
+ "/**/*.css",
+ "/**/*.js"
+ ).permitAll()
+ .antMatchers("/profile/**").anonymous()
+ .antMatchers("/common/download**").anonymous()
+ .antMatchers("/common/download/resource**").anonymous()
+ .antMatchers("/swagger-ui.html").anonymous()
+ .antMatchers("/swagger-resources/**").anonymous()
+ .antMatchers("/webjars/**").anonymous()
+ .antMatchers("/*/api-docs").anonymous()
+ .antMatchers("/druid/**").anonymous()
+ .antMatchers("/websocket/**").anonymous()
+ .antMatchers("/magic/web/**").anonymous()
+ // 除上面外的所有请求全部需要鉴权认证
+ .anyRequest().authenticated()
+ .and()
+ .headers().frameOptions().disable();
+ //单点登录登出
+ httpSecurity.logout().permitAll().logoutSuccessHandler(logoutSuccessHandler);
+ // Custom JWT based security filter
+ httpSecurity.addFilter(casAuthenticationFilter())
+ .addFilterBefore(authenticationTokenFilter, CasAuthenticationFilter.class)
+ //.addFilterBefore(casLogoutFilter(), LogoutFilter.class)
+ .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class).exceptionHandling()
+ //认证失败
+ .authenticationEntryPoint(casAuthenticationEntryPoint());
+
+ // 添加CORS filter
+ httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
+ httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
+ // disable page caching
+ httpSecurity.headers().cacheControl();
+ }
+ }
+
+ /**
+ * 强散列哈希加密实现
+ */
+ @Bean
+ public BCryptPasswordEncoder bCryptPasswordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ /**
+ * 身份认证接口
+ */
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ // cas
+ if (casProperties.isCasEnable()) {
+ super.configure(auth);
+ auth.authenticationProvider(casAuthenticationProvider());
+ }
+ }
+
+
+ /**
+ * 认证的入口
+ */
+ @Bean
+ public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
+ CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
+ casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
+ casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
+ return casAuthenticationEntryPoint;
+ }
+
+ /**
+ * 指定service相关信息
+ */
+ @Bean
+ public ServiceProperties serviceProperties() {
+ ServiceProperties serviceProperties = new ServiceProperties();
+ serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());
+ serviceProperties.setAuthenticateAllArtifacts(true);
+ return serviceProperties;
+ }
+
+ /**
+ * CAS认证过滤器
+ */
+ @Bean
+ public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
+ CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
+ casAuthenticationFilter.setAuthenticationManager(authenticationManager());
+ casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
+ casAuthenticationFilter.setAuthenticationSuccessHandler(casAuthenticationSuccessHandler);
+ return casAuthenticationFilter;
+ }
+
+ /**
+ * cas 认证 Provider
+ */
+ @Bean
+ public CasAuthenticationProvider casAuthenticationProvider() {
+ CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
+ casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService);
+ casAuthenticationProvider.setServiceProperties(serviceProperties());
+ casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
+ casAuthenticationProvider.setKey("casAuthenticationProviderKey");
+ return casAuthenticationProvider;
+ }
+
+ @Bean
+ public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
+ return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());
+ }
+
+ /**
+ * 单点登出过滤器
+ */
+ @Bean
+ public SingleSignOutFilter singleSignOutFilter() {
+ SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
+ singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
+ singleSignOutFilter.setIgnoreInitConfiguration(true);
+ return singleSignOutFilter;
+ }
+
+ /**
+ * 请求单点退出过滤器
+ */
+ @Bean
+ public LogoutFilter casLogoutFilter() {
+ LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(),
+ new SecurityContextLogoutHandler());
+ logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
+ return logoutFilter;
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/TokenService.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/TokenService.java
new file mode 100644
index 00000000..2e1e2782
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/TokenService.java
@@ -0,0 +1,4 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+public class TokenService {
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserDetailsServiceImpl.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserDetailsServiceImpl.java
new file mode 100644
index 00000000..730417cd
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserDetailsServiceImpl.java
@@ -0,0 +1,30 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
+import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+public class UserDetailsServiceImpl implements AuthenticationUserDetailsService {
+ @Override
+ public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
+ System.out.println("getCredentials:" + token.getCredentials());
+ String username = token.getName();
+ System.out.println(username);
+ UserInfo userInfo = new UserInfo();
+ userInfo.setUsername("admin");
+ userInfo.setName("admin");
+ Set authorities = new HashSet();
+ AuthorityInfo authorityInfo = new AuthorityInfo("TEST");
+ authorities.add(authorityInfo);
+ userInfo.setAuthorities(authorities);
+ return userInfo;
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserInfo.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserInfo.java
new file mode 100644
index 00000000..5618f1ae
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserInfo.java
@@ -0,0 +1,98 @@
+package com.unicom.sso.bigdata.cas.demo.config;
+
+import lombok.Getter;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class UserInfo implements UserDetails {
+ private static final long serialVersionUID = -1041327031937199938L;
+
+ /**
+ * 用户ID
+ */
+ @Getter
+ private Long id;
+
+ /**
+ * 用户名称
+ */
+ @Getter
+ private String name;
+
+ /**
+ * 登录名称
+ */
+ @Getter
+ private String username;
+
+ /**
+ * 登录密码
+ */
+ @Getter
+ private String password;
+
+ private boolean isAccountNonExpired = true;
+
+ private boolean isAccountNonLocked = true;
+
+ private boolean isCredentialsNonExpired = true;
+
+ private boolean isEnabled = true;
+
+ @Getter
+ private Set authorities = new HashSet();
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isAccountNonExpired() {
+ return isAccountNonExpired;
+ }
+
+ public void setAccountNonExpired(boolean accountNonExpired) {
+ isAccountNonExpired = accountNonExpired;
+ }
+
+ public boolean isAccountNonLocked() {
+ return isAccountNonLocked;
+ }
+
+ public void setAccountNonLocked(boolean accountNonLocked) {
+ isAccountNonLocked = accountNonLocked;
+ }
+
+ public boolean isCredentialsNonExpired() {
+ return isCredentialsNonExpired;
+ }
+
+ public void setCredentialsNonExpired(boolean credentialsNonExpired) {
+ isCredentialsNonExpired = credentialsNonExpired;
+ }
+
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ isEnabled = enabled;
+ }
+
+ public void setAuthorities(Set authorities) {
+ this.authorities = authorities;
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/HelloController.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/HelloController.java
new file mode 100644
index 00000000..8ab815f8
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/HelloController.java
@@ -0,0 +1,63 @@
+package com.unicom.sso.bigdata.cas.demo.controller;
+
+import org.jasig.cas.client.util.AbstractCasFilter;
+import org.jasig.cas.client.validation.Assertion;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * cas 回调地址
+ * @author baihz10
+ * @date 2023/7/7 15:44
+ */
+@Controller
+public class HelloController {
+
+ @GetMapping("/hello")
+ public String home(Model model, HttpServletRequest request) {
+// String token =request.getParameter("token");
+// System.out.println("token : "+token);
+// Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
+//
+// String username= assertion.getPrincipal().getName();
+// System.out.println("cas user:"+username);
+//
+// username = Optional.ofNullable(username).orElse("anonymous");
+// Map attributes = Optional.ofNullable(assertion.getPrincipal().getAttributes()).orElse(new HashMap<>());
+//
+// model.addAttribute("username", username);
+
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ System.out.println("当前用户信息:" + auth.getPrincipal());
+ return "home";
+ }
+
+ @GetMapping("/hello2")
+ public String home2(Model model, HttpServletRequest request) {
+ String token =request.getParameter("token");
+ System.out.println("token : "+token);
+ Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
+
+ String username= assertion.getPrincipal().getName();
+ System.out.println("cas user:"+username);
+
+ username = Optional.ofNullable(username).orElse("anonymous");
+ Map attributes = Optional.ofNullable(assertion.getPrincipal().getAttributes()).orElse(new HashMap<>());
+
+ model.addAttribute("username", username);
+
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ System.out.println("当前用户信息:" + auth.getPrincipal());
+ return "home";
+ }
+
+
+}
diff --git a/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/SsoLoginController.java b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/SsoLoginController.java
new file mode 100644
index 00000000..96f77456
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/SsoLoginController.java
@@ -0,0 +1,29 @@
+package com.unicom.sso.bigdata.cas.demo.controller;
+
+import org.jasig.cas.client.util.AbstractCasFilter;
+import org.jasig.cas.client.validation.Assertion;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Optional;
+
+/**
+ * 控制类
+ * @author baihz10
+ * @date 2023/7/7 15:44
+ */
+@Controller
+public class SsoLoginController {
+
+ @GetMapping("/caslogin")
+ public String home(Model model,HttpServletRequest request) {
+ Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
+
+ String username= assertion.getPrincipal().getName();
+ username = Optional.ofNullable(username).orElse("anonymous");
+ model.addAttribute("username", username);
+ return "cas/login";
+ }
+}
diff --git a/integrations/spring-security-cas-demo/src/main/resources/application.properties b/integrations/spring-security-cas-demo/src/main/resources/application.properties
new file mode 100644
index 00000000..8ce98040
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/resources/application.properties
@@ -0,0 +1,25 @@
+server.port=10002
+
+#spring.profiles.active=cas-test
+
+base.url=http://cas.demo.maxkey.top:10002
+cas.server.url=http://192.168.202.102:8080/sign/authz/cas
+
+#CAS
+cas.server.host.url=http://192.168.202.102:8080/sign/authz/cas
+#CAS????
+
+#CAS??????
+cas.server.host.login_url=${cas.server.host.url}/login
+#CAS??????
+cas.server.host.logout_url=${cas.server.host.url}/logout?service=${app.server.host.url}
+# ??????
+app.casEnable=true
+app.server.host.url=http://192.168.202.102:${server.port}
+
+#??????
+app.server.host.login_url=/
+#??????
+app.server.host.logout_url=/logout
+#??????
+app.server.host.web_url=http://192.168.202.102/index
\ No newline at end of file
diff --git a/integrations/spring-security-cas-demo/src/main/resources/templates/cas/login.html b/integrations/spring-security-cas-demo/src/main/resources/templates/cas/login.html
new file mode 100644
index 00000000..9037cfa7
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/resources/templates/cas/login.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ sso cas demo
+
+
+
+Login with CAS
+login user : [[${username}]]
+
+
\ No newline at end of file
diff --git a/integrations/spring-security-cas-demo/src/main/resources/templates/home.html b/integrations/spring-security-cas-demo/src/main/resources/templates/home.html
new file mode 100644
index 00000000..97284838
--- /dev/null
+++ b/integrations/spring-security-cas-demo/src/main/resources/templates/home.html
@@ -0,0 +1,13 @@
+
+
+
+
+ home
+
+
+hello cas
+
+hello [[${username}]]
+userInfo: [[${userInfo}]]
+
+
\ No newline at end of file