Browse Source

spring-security-cas-demo

mjh 1 year ago
parent
commit
5eabd4892c
17 changed files with 1121 additions and 0 deletions
  1. 50 0
      integrations/spring-security-cas-demo/pom.xml
  2. 17 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/CasApplication.java
  3. 25 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/AuthorityInfo.java
  4. 120 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasConfig.java
  5. 96 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CasProperties.java
  6. 17 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/CustomUserDetailsService.java
  7. 37 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/JwtAuthenticationTokenFilter.java
  8. 233 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/LoginUser.java
  9. 251 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/SecurityConfig.java
  10. 4 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/TokenService.java
  11. 30 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserDetailsServiceImpl.java
  12. 98 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/config/UserInfo.java
  13. 63 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/HelloController.java
  14. 29 0
      integrations/spring-security-cas-demo/src/main/java/com/unicom/sso/bigdata/cas/demo/controller/SsoLoginController.java
  15. 25 0
      integrations/spring-security-cas-demo/src/main/resources/application.properties
  16. 13 0
      integrations/spring-security-cas-demo/src/main/resources/templates/cas/login.html
  17. 13 0
      integrations/spring-security-cas-demo/src/main/resources/templates/home.html

+ 50 - 0
integrations/spring-security-cas-demo/pom.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.unicom.sso</groupId>
+        <artifactId>sso-springboot-sample</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>sso-bigdata-cas-starter-demo</artifactId>
+    <description>cas 单点登录demo</description>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+
+
+        <!--单点登录依赖-->
+<!--        <dependency>-->
+<!--            <groupId>com.unicom.sso</groupId>-->
+<!--            <artifactId>unicom-sso-bigdata-cas-springboot-starter</artifactId>-->
+<!--            <version>0.0.1-SNAPSHOT</version>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-cas</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 17 - 0
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);
+    }
+}

+ 25 - 0
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;
+    }
+}

+ 120 - 0
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;
+    }
+
+}

+ 96 - 0
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;
+    }
+
+}

+ 17 - 0
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"));
+    }
+}

+ 37 - 0
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);
+    }
+}
+

+ 233 - 0
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<String> 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<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> 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;
+    }
+}

+ 251 - 0
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;
+    }
+}

+ 4 - 0
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 {
+}

+ 30 - 0
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<CasAssertionAuthenticationToken> {
+    @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<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();
+        AuthorityInfo authorityInfo = new AuthorityInfo("TEST");
+        authorities.add(authorityInfo);
+        userInfo.setAuthorities(authorities);
+        return userInfo;
+    }
+}

+ 98 - 0
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<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();
+
+    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<AuthorityInfo> authorities) {
+        this.authorities = authorities;
+    }
+}

+ 63 - 0
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<String, Object> 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<String, Object> 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";
+    }
+
+
+}

+ 29 - 0
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";
+    }
+}

+ 25 - 0
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

+ 13 - 0
integrations/spring-security-cas-demo/src/main/resources/templates/cas/login.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+    <title>sso cas demo</title>
+</head>
+
+<body>
+<h2 >Login with CAS</h2>
+login user : [[${username}]]
+</body>
+</html>

+ 13 - 0
integrations/spring-security-cas-demo/src/main/resources/templates/home.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>home</title>
+</head>
+<body>
+hello cas
+<br>
+hello [[${username}]]
+userInfo: [[${userInfo}]]
+</body>
+</html>