wangqiang 1 ano atrás
pai
commit
faec220c4b
19 arquivos alterados com 894 adições e 80 exclusões
  1. 32 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/CasProperties.java
  2. 92 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutFilter.java
  3. 254 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutHandler.java
  4. 34 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutHttpSessionListener.java
  5. 13 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/TestCas.java
  6. 108 13
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/WebSecurityConfig.java
  7. 19 26
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/service/CustomUserDetailsService.java
  8. 30 0
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/CasRestClient.java
  9. 20 4
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/LoginController.java
  10. 42 17
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/UserController.java
  11. 2 2
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/mapper/xml/UserMapper.xml
  12. 20 2
      jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/service/UserService.java
  13. 1 0
      jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/config/RestTemplateConfig.java
  14. 53 0
      jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/controller/ccpm/TestController.java
  15. 11 0
      jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/utils/RestTemplateService.java
  16. 130 0
      jeeplus-web/src/main/java/com/jeeplus/config/MyInterceptor.java
  17. 6 1
      jeeplus-web/src/main/java/com/jeeplus/config/WebConfig.java
  18. 15 15
      jeeplus-web/src/main/resources/application-development.yml
  19. 12 0
      pom.xml

+ 32 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/CasProperties.java

@@ -0,0 +1,32 @@
+package com.jeeplus.security.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * CAS的配置参数
+ * @author: 王强
+ * @create: 2023-04-20 10:40
+ **/
+@Component
+@Data
+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("${cas.app_server_host_url}")
+    private String appServerUrl;
+
+    @Value("${cas.app_login_url}")
+    private String appLoginUrl;
+
+    @Value("${cas.app_logout_url}")
+    private String appLogoutUrl;
+}

+ 92 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutFilter.java

@@ -0,0 +1,92 @@
+package com.jeeplus.security.config;
+
+/**
+ * @author: 王强
+ * @create: 2023-04-25 16:16
+ **/
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.configuration.ConfigurationKeys;
+import org.jasig.cas.client.session.SessionMappingStorage;
+import org.jasig.cas.client.util.AbstractConfigurationFilter;
+import org.jasig.cas.client.validation.Assertion;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidationException;
+import org.jasig.cas.client.validation.TicketValidator;
+
+public final class SingleSignOutFilter extends AbstractConfigurationFilter {
+    private static final SingleSignOutHandler HANDLER = new SingleSignOutHandler();
+    private AtomicBoolean handlerInitialized = new AtomicBoolean(false);
+
+    public SingleSignOutFilter() {
+    }
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+        super.init(filterConfig);
+        if (!this.isIgnoreInitConfiguration()) {
+            this.setArtifactParameterName(this.getString(ConfigurationKeys.ARTIFACT_PARAMETER_NAME));
+            this.setLogoutParameterName(this.getString(ConfigurationKeys.LOGOUT_PARAMETER_NAME));
+            this.setRelayStateParameterName(this.getString(ConfigurationKeys.RELAY_STATE_PARAMETER_NAME));
+            this.setCasServerUrlPrefix(this.getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX));
+            this.setLogoutCallbackPath(this.getString(ConfigurationKeys.LOGOUT_CALLBACK_PATH));
+            HANDLER.setArtifactParameterOverPost(this.getBoolean(ConfigurationKeys.ARTIFACT_PARAMETER_OVER_POST));
+            HANDLER.setEagerlyCreateSessions(this.getBoolean(ConfigurationKeys.EAGERLY_CREATE_SESSIONS));
+        }
+
+        HANDLER.init();
+        this.handlerInitialized.set(true);
+    }
+
+    public void setArtifactParameterName(String name) {
+        HANDLER.setArtifactParameterName(name);
+    }
+
+    public void setLogoutParameterName(String name) {
+        HANDLER.setLogoutParameterName(name);
+    }
+
+    public void setRelayStateParameterName(String name) {
+        HANDLER.setRelayStateParameterName(name);
+    }
+
+    public void setCasServerUrlPrefix(String casServerUrlPrefix) {
+        HANDLER.setCasServerUrlPrefix(casServerUrlPrefix);
+    }
+
+    public void setLogoutCallbackPath(String logoutCallbackPath) {
+        HANDLER.setLogoutCallbackPath(logoutCallbackPath);
+    }
+
+    public void setSessionMappingStorage(SessionMappingStorage storage) {
+        HANDLER.setSessionMappingStorage(storage);
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        HttpServletRequest request = (HttpServletRequest)servletRequest;
+        HttpServletResponse response = (HttpServletResponse)servletResponse;
+        if (!this.handlerInitialized.getAndSet(true)) {
+            HANDLER.init();
+        }
+
+        if (HANDLER.process(request, response)) {
+            filterChain.doFilter(servletRequest, servletResponse);
+        }
+
+    }
+
+    public void destroy() {
+    }
+
+    protected static SingleSignOutHandler getSingleSignOutHandler() {
+        return HANDLER;
+    }
+}

+ 254 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutHandler.java

@@ -0,0 +1,254 @@
+package com.jeeplus.security.config;
+
+/**
+ * @author: 王强
+ * @create: 2023-04-25 16:19
+ **/
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.zip.Inflater;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.xml.bind.DatatypeConverter;
+import org.jasig.cas.client.Protocol;
+import org.jasig.cas.client.configuration.ConfigurationKeys;
+import org.jasig.cas.client.session.HashMapBackedSessionMappingStorage;
+import org.jasig.cas.client.session.SessionMappingStorage;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.util.XmlUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SingleSignOutHandler {
+    private static final int DECOMPRESSION_FACTOR = 10;
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    private SessionMappingStorage sessionMappingStorage = new HashMapBackedSessionMappingStorage();
+    private String artifactParameterName;
+    private String logoutParameterName;
+    private String relayStateParameterName;
+    private String casServerUrlPrefix;
+    private String logoutCallbackPath;
+    private boolean artifactParameterOverPost;
+    private boolean eagerlyCreateSessions;
+    private List<String> safeParameters;
+    private final LogoutStrategy logoutStrategy;
+
+    public SingleSignOutHandler() {
+        this.artifactParameterName = Protocol.CAS2.getArtifactParameterName();
+        this.logoutParameterName = (String)ConfigurationKeys.LOGOUT_PARAMETER_NAME.getDefaultValue();
+        this.relayStateParameterName = (String)ConfigurationKeys.RELAY_STATE_PARAMETER_NAME.getDefaultValue();
+        this.casServerUrlPrefix = "";
+        this.artifactParameterOverPost = false;
+        this.eagerlyCreateSessions = true;
+        this.logoutStrategy = (LogoutStrategy)(isServlet30() ? new Servlet30LogoutStrategy() : new Servlet25LogoutStrategy());
+    }
+
+    public void setSessionMappingStorage(SessionMappingStorage storage) {
+        this.sessionMappingStorage = storage;
+    }
+
+    public void setArtifactParameterOverPost(boolean artifactParameterOverPost) {
+        this.artifactParameterOverPost = artifactParameterOverPost;
+    }
+
+    public SessionMappingStorage getSessionMappingStorage() {
+        return this.sessionMappingStorage;
+    }
+
+    public void setArtifactParameterName(String name) {
+        this.artifactParameterName = name;
+    }
+
+    public void setLogoutParameterName(String name) {
+        this.logoutParameterName = name;
+    }
+
+    public void setCasServerUrlPrefix(String casServerUrlPrefix) {
+        this.casServerUrlPrefix = casServerUrlPrefix;
+    }
+
+    public void setLogoutCallbackPath(String logoutCallbackPath) {
+        this.logoutCallbackPath = logoutCallbackPath;
+    }
+
+    public void setRelayStateParameterName(String name) {
+        this.relayStateParameterName = name;
+    }
+
+    public void setEagerlyCreateSessions(boolean eagerlyCreateSessions) {
+        this.eagerlyCreateSessions = eagerlyCreateSessions;
+    }
+
+    public synchronized void init() {
+        if (this.safeParameters == null) {
+            CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
+            CommonUtils.assertNotNull(this.logoutParameterName, "logoutParameterName cannot be null.");
+            CommonUtils.assertNotNull(this.sessionMappingStorage, "sessionMappingStorage cannot be null.");
+            CommonUtils.assertNotNull(this.relayStateParameterName, "relayStateParameterName cannot be null.");
+            CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
+            if (CommonUtils.isBlank(this.casServerUrlPrefix)) {
+                this.logger.warn("Front Channel single sign out redirects are disabled when the 'casServerUrlPrefix' value is not set.");
+            }
+
+            if (this.artifactParameterOverPost) {
+                this.safeParameters = Arrays.asList(this.logoutParameterName, this.artifactParameterName);
+            } else {
+                this.safeParameters = Collections.singletonList(this.logoutParameterName);
+            }
+        }
+
+    }
+
+    private boolean isTokenRequest(HttpServletRequest request) {
+        return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters));
+    }
+
+    private boolean isLogoutRequest(HttpServletRequest request) {
+        if (!"POST".equalsIgnoreCase(request.getMethod())) {
+            return "GET".equalsIgnoreCase(request.getMethod()) ? CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters)) : false;
+        } else {
+            return !this.isMultipartRequest(request) && this.pathEligibleForLogout(request) && CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters));
+        }
+    }
+
+    private boolean pathEligibleForLogout(HttpServletRequest request) {
+        return this.logoutCallbackPath == null || this.logoutCallbackPath.equals(this.getPath(request));
+    }
+
+    private String getPath(HttpServletRequest request) {
+        return request.getServletPath() + CommonUtils.nullToEmpty(request.getPathInfo());
+    }
+
+    public boolean process(HttpServletRequest request, HttpServletResponse response) {
+        if (this.isTokenRequest(request)) {
+            this.logger.trace("Received a token request");
+            this.recordSession(request);
+            return true;
+        } else if (this.isLogoutRequest(request)) {
+            //第二种情况, 其他客户端退出
+            TestCas.name = "logout";
+            TestCas.is = true;
+
+            this.logger.trace("Received a logout request");
+            this.destroySession(request);
+
+            return false;
+        } else {
+            this.logger.trace("Ignoring URI for logout: {}", request.getRequestURI());
+            return true;
+        }
+    }
+
+    private void recordSession(HttpServletRequest request) {
+        HttpSession session = request.getSession(this.eagerlyCreateSessions);
+        if (session == null) {
+            this.logger.debug("No session currently exists (and none created).  Cannot record session information for single sign out.");
+        } else {
+            String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters);
+            this.logger.debug("Recording session for token {}", token);
+
+            try {
+                this.sessionMappingStorage.removeBySessionById(session.getId());
+            } catch (Exception var5) {
+            }
+
+            this.sessionMappingStorage.addSessionById(token, session);
+        }
+    }
+
+    private String uncompressLogoutMessage(String originalMessage) {
+        byte[] binaryMessage = DatatypeConverter.parseBase64Binary(originalMessage);
+        Inflater decompresser = null;
+
+        String var6;
+        try {
+            decompresser = new Inflater();
+            decompresser.setInput(binaryMessage);
+            byte[] result = new byte[binaryMessage.length * 10];
+            int resultLength = decompresser.inflate(result);
+            var6 = new String(result, 0, resultLength, "UTF-8");
+        } catch (Exception var10) {
+            this.logger.error("Unable to decompress logout message", var10);
+            throw new RuntimeException(var10);
+        } finally {
+            if (decompresser != null) {
+                decompresser.end();
+            }
+
+        }
+
+        return var6;
+    }
+
+    private void destroySession(HttpServletRequest request) {
+        String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);
+        if (CommonUtils.isBlank(logoutMessage)) {
+            this.logger.error("Could not locate logout message of the request from {}", this.logoutParameterName);
+        } else {
+            if (!logoutMessage.contains("SessionIndex")) {
+                logoutMessage = this.uncompressLogoutMessage(logoutMessage);
+            }
+
+            this.logger.trace("Logout request:\n{}", logoutMessage);
+            String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");
+            if (CommonUtils.isNotBlank(token)) {
+                HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);
+                if (session != null) {
+                    String sessionID = session.getId();
+                    this.logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);
+
+                    try {
+                        session.invalidate();
+                    } catch (IllegalStateException var7) {
+                        this.logger.debug("Error invalidating session.", var7);
+                    }
+
+                    this.logoutStrategy.logout(request);
+                }
+            }
+
+        }
+    }
+
+    private boolean isMultipartRequest(HttpServletRequest request) {
+        return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart");
+    }
+
+    private static boolean isServlet30() {
+        try {
+            return HttpServletRequest.class.getMethod("logout") != null;
+        } catch (NoSuchMethodException var1) {
+            return false;
+        }
+    }
+
+    private class Servlet30LogoutStrategy implements LogoutStrategy {
+        private Servlet30LogoutStrategy() {
+        }
+
+        public void logout(HttpServletRequest request) {
+            try {
+                request.logout();
+            } catch (ServletException var3) {
+                logger.debug("Error performing request.logout.");
+            }
+
+        }
+    }
+
+    private class Servlet25LogoutStrategy implements LogoutStrategy {
+        private Servlet25LogoutStrategy() {
+        }
+
+        public void logout(HttpServletRequest request) {
+        }
+    }
+
+    private interface LogoutStrategy {
+        void logout(HttpServletRequest var1);
+    }
+}
+

+ 34 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/SingleSignOutHttpSessionListener.java

@@ -0,0 +1,34 @@
+package com.jeeplus.security.config;
+
+import org.jasig.cas.client.session.SessionMappingStorage;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+/**
+ * @author: 王强
+ * @create: 2023-04-25 16:21
+ **/
+public final class SingleSignOutHttpSessionListener implements HttpSessionListener {
+    private SessionMappingStorage sessionMappingStorage;
+
+    public SingleSignOutHttpSessionListener() {
+    }
+
+    public void sessionCreated(HttpSessionEvent event) {
+    }
+
+    public void sessionDestroyed(HttpSessionEvent event) {
+        if (this.sessionMappingStorage == null) {
+            this.sessionMappingStorage = getSessionMappingStorage();
+        }
+
+        HttpSession session = event.getSession();
+        this.sessionMappingStorage.removeBySessionById(session.getId());
+    }
+
+    protected static SessionMappingStorage getSessionMappingStorage() {
+        return SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage();
+    }
+}

+ 13 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/TestCas.java

@@ -0,0 +1,13 @@
+package com.jeeplus.security.config;
+
+/**
+ * @author: 王强
+ * @create: 2023-04-27 17:51
+ **/
+public class TestCas {
+
+    public static String name;
+    public static String urlName;
+    public static boolean is;
+
+}

+ 108 - 13
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/config/WebSecurityConfig.java

@@ -6,10 +6,16 @@ import com.jeeplus.security.jwt.JWTConfigurer;
 import com.jeeplus.security.jwt.TokenProvider;
 import com.jeeplus.security.service.CustomUserDetailsService;
 import com.jeeplus.security.util.DaoAuthenticationProvider;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
 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.CasAssertionAuthenticationToken;
+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;
@@ -17,46 +23,59 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
 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.AuthenticationUserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
 
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-    @Autowired
-    private CustomUserDetailsService userDatailService;
+    //    @Autowired
+//    private CustomUserDetailsService userDatailService;
     @Autowired
     private  JwtAuthenticationEntryPoint unauthorizedHandler;
     @Autowired
     private JwtAccessDeniedHandler accessDeniedHandler;
 
+    @Autowired
+    private CasProperties casProperties;
 
     /**
      * 描述:设置授权处理相关的具体类以及加密方式
      */
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-        // 设置不隐藏 未找到用户异常
-        provider.setHideUserNotFoundExceptions(true);
-        // 用户认证service - 查询数据库的逻辑
-        provider.setUserDetailsService(userDetailsService());
-        // 设置密码加密算法
-        provider.setPasswordEncoder(passwordEncoder());
-        provider.setUserDetailsService ( userDatailService );
-        auth.authenticationProvider(provider);
+//        super.configure(auth);
+        auth.authenticationProvider(casAuthenticationProvider());
+//        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+//        // 设置不隐藏 未找到用户异常
+//        provider.setHideUserNotFoundExceptions(true);
+//        // 用户认证service - 查询数据库的逻辑
+//        provider.setUserDetailsService(userDetailsService());
+//        // 设置密码加密算法
+//        provider.setPasswordEncoder(passwordEncoder());
+//        provider.setUserDetailsService ( userDatailService );
+//        auth.authenticationProvider(provider);
     }
 
 
     @Override
     protected void configure(HttpSecurity http) throws Exception {
-            http
+//        http.authorizeRequests()//配置安全策略
+//                .antMatchers("/", "/hello").permitAll()//定义请求不需要验证
+//            .anyRequest().authenticated()//其余的所有请求都需要验证
+//            .and().logout().permitAll()//定义logout不需要验证
+//            .and().formLogin();//使用form表单登录
+
+        http
                 .headers().frameOptions().disable ().and ()
                 .exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()
                 // 由于使用的是JWT,我们这里不需要csrf
                 .csrf().disable()
                 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                 // 基于token,所以不需要session
-                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+//                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                 .authorizeRequests()
                 .antMatchers ( "/401"
                         ,"/404",
@@ -71,6 +90,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                         "/sys/sysConfig/getConfig",
                         "/getAppFlowChart",
                         "/sys/getCode",
+                        "/sys/logout",
+                        "/test/savePwd",
                         "/sys/getLoginCodeNumber",
                         "/cwProjectReport/signatureCallBack/**",
                         "/app/sys/getCode",
@@ -82,6 +103,13 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .anyRequest().authenticated() // 所有请求都需要验证
                 .and ()
                 .apply(securityConfigurerAdapter());
+
+        http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())
+                .and()
+                .addFilter(casAuthenticationFilter())
+                .addFilterBefore(casLogoutFilter(),LogoutFilter.class)
+                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);
+
     }
 
     /**
@@ -100,6 +128,73 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                         "/webjars/**");
     }
 
+    /**认证的入口*/
+    @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());
+        return casAuthenticationFilter;
+    }
+
+    /**cas 认证 Provider*/
+    @Bean
+    public CasAuthenticationProvider casAuthenticationProvider() {
+        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
+        casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());
+        //casAuthenticationProvider.setUserDetailsService(customUserDetailsService()); //这里只是接口类型,实现的接口不一样,都可以的。
+        casAuthenticationProvider.setServiceProperties(serviceProperties());
+        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
+        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
+        return casAuthenticationProvider;
+    }
+
+    /**用户自定义的AuthenticationUserDetailsService*/
+    @Bean
+    public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService(){
+        return new CustomUserDetailsService();
+    }
+
+    @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.getAppServerUrl() + casProperties.getAppLogoutUrl());
+        return logoutFilter;
+    }
+
     /**
      * 描述: 密码加密算法 BCrypt 推荐使用
      **/

+ 19 - 26
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/security/service/CustomUserDetailsService.java

@@ -6,43 +6,36 @@ import com.jeeplus.sys.service.UserService;
 import com.jeeplus.sys.service.dto.UserDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
 import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.*;
 import org.springframework.stereotype.Component;
 
 import java.util.ArrayList;
 import java.util.List;
 
-@Component
-public class CustomUserDetailsService implements UserDetailsService {
+/**
+ * 用于加载用户信息
+ * @author: 王强
+ * @create: 2023-04-20 10:40
+ **/
+public class CustomUserDetailsService implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
     @Autowired
     private UserService userService;
 
-    @Override
-    public User loadUserByUsername(String username) throws UsernameNotFoundException {
-        // 通过用户名从数据库获取用户信息
-        UserDTO userInfo =  userService.getUserByLoginName ( username );
-
-        // 用户不存在
-        if (userInfo == null) {
-            throw new AccountExpiredException (ErrorConstants.LOGIN_ERROR_NOTFOUND);
-        }
 
-        // 用户禁止登录
-        if ( CommonConstants.NO.equals ( userInfo.getLoginFlag ( ) ) ) {
-            throw new AccountExpiredException ( ErrorConstants.LOGIN_ERROR_FORBIDDEN );
-        }
-
-        // 权限集合
-        List <GrantedAuthority> authorities = new ArrayList <> ();
+    /**
+     * 当cas登录成功后会进入到这里
+     * @param token
+     * @return
+     * @throws UsernameNotFoundException
+     */
+    @Override
+    public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
+        System.out.println(token.getName());
+        return new User(token.getName(), "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
 
-        return new User (
-                userInfo.getLoginName (),
-                userInfo.getPassword(),
-                authorities
-        );
     }
 }
 

+ 30 - 0
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/CasRestClient.java

@@ -0,0 +1,30 @@
+package com.jeeplus.sys.controller;
+
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.validation.Assertion;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidationException;
+import org.jasig.cas.client.validation.TicketValidator;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * @author: 王强
+ * @create: 2023-05-05 15:51
+ **/
+public class CasRestClient {
+
+    public String getCasUserInfo(String ticket,String service,String casServer) throws TicketValidationException {
+        //ticket检验器
+        TicketValidator ticketValidator = new Cas20ServiceTicketValidator( casServer );
+        // 去CAS服务端中验证ticket的合法性
+        Assertion casAssertion = ticketValidator.validate ( ticket, service );
+        // 从CAS服务端中获取相关属性,包括用户名、是否设置RememberMe等
+        AttributePrincipal casPrincipal = casAssertion.getPrincipal ( );
+        String loginName = casPrincipal.getName ( );
+        return loginName;
+    }
+}

+ 20 - 4
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/LoginController.java

@@ -15,6 +15,7 @@ import com.jeeplus.common.utils.RequestUtils;
 import com.jeeplus.common.utils.ResponseUtil;
 import com.jeeplus.config.properties.JeePlusProperties;
 import com.jeeplus.core.errors.ErrorConstants;
+import com.jeeplus.security.config.TestCas;
 import com.jeeplus.security.jwt.TokenProvider;
 import com.jeeplus.security.util.DaoAuthenticationProvider;
 import com.jeeplus.security.util.SecurityUtils;
@@ -44,8 +45,10 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.connection.jedis.JedisUtils;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.authentication.*;
+import org.springframework.security.cas.authentication.CasAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
@@ -172,7 +175,7 @@ public class LoginController {
     @ApiLog(value = "单点登录", type = LogTypeEnum.ACCESS)
     @RequestMapping("/sys/casLogin")
     public ResponseEntity casLogin(@RequestParam(name = "ticket") String ticket,
-                                   @RequestParam(name = "service") String service, @Value("${cas.server-url-prefix}") String casServer) throws Exception {
+                                   @RequestParam(name = "service") String service, @Value("${cas.server_host_url}") String casServer) throws Exception {
         //ticket检验器
         TicketValidator ticketValidator = new Cas20ServiceTicketValidator ( casServer );
         ResponseUtil responseUtil = new ResponseUtil ( );
@@ -194,13 +197,18 @@ public class LoginController {
                 Authentication authentication = TokenProvider.getAuthentication ( token );
                 SecurityContextHolder.getContext ( ).setAuthentication ( authentication );
 
+                responseUtil.add( TokenProvider.TOKEN, token);
                 // 更新登录信息
                 updateUserLoginInfo ( responseUtil, userDTO, token );
-
+                userDTO.setToken(token);
+                //将登录的用户信息存放到redis中(在线状态key中)
+                RedisUtils.getInstance().set(CacheNames.USER_CACHE_LOGIN_ONLINE_LOGIN_NAME + loginName , userDTO);
                 return responseUtil.ok ();
             } else {
-                AuthenticationException e = new UsernameNotFoundException ( ErrorConstants.LOGIN_ERROR_NOTFOUND );
+//                AuthenticationException e = new UsernameNotFoundException ( ErrorConstants.LOGIN_ERROR_NOTFOUND );
+                AuthenticationException e = new UsernameNotFoundException ( "用户:" + loginName + "  不存在!" );
                 log.error ( "用户【loginName:" + loginName + "】不存在!", e );
+
                 throw e;
             }
         } catch (TicketValidationException e) {
@@ -235,9 +243,14 @@ public class LoginController {
      */
     @ApiOperation("退出登录")
     @ApiLog(value = "退出登录", type = LogTypeEnum.LOGIN)
-    @GetMapping("/sys/logout")
+    @PostMapping("/sys/logout")
     public ResponseEntity logout(HttpServletRequest request, HttpServletResponse response) {
         Authentication auth = SecurityUtils.getAuthentication ();
+
+        if (TestCas.is){
+            TestCas.is = false;
+        }
+
         if ( auth != null ) {
             UserUtils.deleteCache (UserUtils.getCurrentUserDTO () );
             String token = TokenProvider.resolveToken(request);
@@ -245,7 +258,10 @@ public class LoginController {
             //删除员工登录在线redis信息
             String key = CacheNames.USER_CACHE_LOGIN_ONLINE_LOGIN_NAME + UserUtils.getCurrentUserDTO ().getLoginName ();
             redisUtils.delete  (key);
+            HttpSession session = request.getSession();
+            session.invalidate();
             new SecurityContextLogoutHandler ( ).logout ( request, response, auth );
+
         }
         return ResponseEntity.ok ( "退出成功" );
     }

+ 42 - 17
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/controller/UserController.java

@@ -43,8 +43,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.parameters.P;
-import org.springframework.util.ObjectUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -53,7 +51,6 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.ConstraintViolationException;
 import javax.validation.Valid;
 import javax.validation.Validator;
-import javax.validation.constraints.NotNull;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -90,6 +87,9 @@ public class UserController {
     @Autowired
     private OfficeWrapper officeWrapper;
 
+    @Resource
+    private RestTemplateService2 restTemplateService2;
+
     /**
      * 根据id查询用户
      *
@@ -533,25 +533,50 @@ public class UserController {
     }
 
 
+//    @DemoMode
+//    @ApiLog("修改密码")
+//    @RequestMapping("savePwd")
+//    @ApiOperation(value = "修改密码")
+//    public ResponseEntity savePwd(String oldPassword, String newPassword) {
+//        UserDTO userDTO = UserUtils.getCurrentUserDTO ( );
+//        if ( StrUtil.isNotBlank ( oldPassword ) && StrUtil.isNotBlank ( newPassword ) ) {
+//            if ( SecurityUtils.validatePassword ( oldPassword, userDTO.getPassword ( ) ) ) {
+//                User user = new User ( userDTO.getId ( ) );
+//                user.setPassword ( SecurityUtils.encryptPassword ( newPassword ) );
+//                user.setUpPassword("1"); // 密码修改状态改为”已修改“
+//                userService.updateById ( user );
+//                UserUtils.deleteCache ( userDTO );
+//                return ResponseEntity.ok ( "修改密码成功!" );
+//            } else {
+//                return ResponseEntity.badRequest ( ).body ( "修改密码失败,旧密码错误!" );
+//            }
+//        }
+//        return ResponseEntity.badRequest ( ).body ( "参数错误!" );
+//    }
+
     @DemoMode
     @ApiLog("修改密码")
     @RequestMapping("savePwd")
     @ApiOperation(value = "修改密码")
-    public ResponseEntity savePwd(String oldPassword, String newPassword) {
+    public ResponseEntity savePwd(String newPassword) {
         UserDTO userDTO = UserUtils.getCurrentUserDTO ( );
-        if ( StrUtil.isNotBlank ( oldPassword ) && StrUtil.isNotBlank ( newPassword ) ) {
-            if ( SecurityUtils.validatePassword ( oldPassword, userDTO.getPassword ( ) ) ) {
-                User user = new User ( userDTO.getId ( ) );
-                user.setPassword ( SecurityUtils.encryptPassword ( newPassword ) );
-                user.setUpPassword("1"); // 密码修改状态改为”已修改“
-                userService.updateById ( user );
-                UserUtils.deleteCache ( userDTO );
-                return ResponseEntity.ok ( "修改密码成功!" );
-            } else {
-                return ResponseEntity.badRequest ( ).body ( "修改密码失败,旧密码错误!" );
-            }
-        }
-        return ResponseEntity.badRequest ( ).body ( "参数错误!" );
+        //调用服务端的修改密码接口
+//        User user = new User ( userDTO.getId ( ) );
+//        user.setPassword ( SecurityUtils.encryptPassword ( newPassword ) );
+//        user.setUpPassword("1"); // 密码修改状态改为”已修改“
+//        userService.updateById ( user );
+//        UserUtils.deleteCache ( userDTO );
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("name", userDTO.getName());
+        paramMap.put("password", newPassword);
+        paramMap.put("mobile", userDTO.getMobile());
+        String token = "";
+
+        Object res = restTemplateService2.getCas("/test/update", token, null);
+
+
+        return ResponseEntity.ok ( "修改密码成功!" );
+
     }
 
 

+ 2 - 2
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/mapper/xml/UserMapper.xml

@@ -55,7 +55,7 @@
 		a.login_date AS "loginDate",
 		a.remarks,
 		a.login_flag,
-		a.other_service_flag,
+-- 		a.other_service_flag,
 		a.photo,
 		a.qr_code,
 		a.sign,
@@ -114,7 +114,7 @@
 		a.login_date AS "loginDate",
 		a.remarks,
 		a.login_flag,
-		a.other_service_flag,
+-- 		a.other_service_flag,
 		a.photo,
 		a.qr_code,
 		a.sign,

+ 20 - 2
jeeplus-platform/jeeplus-admin/src/main/java/com/jeeplus/sys/service/UserService.java

@@ -36,6 +36,8 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -47,6 +49,9 @@ import java.util.stream.Collectors;
 @Transactional
 public class UserService  extends ServiceImpl<UserMapper, User> {
 
+	// 通过 -?[0-9]+(\\\\.[0-9]+)? 进行匹配是否为数字
+	private static Pattern pattern = Pattern.compile("-?[0-9]+(\\\\.[0-9]+)?");
+
 	@Autowired
 	private UserWrapper userWrapper;
 
@@ -114,10 +119,23 @@ public class UserService  extends ServiceImpl<UserMapper, User> {
 	@Cacheable(cacheNames = CacheNames.USER_CACHE_LOGIN_NAME, key = "#loginName")
 	public UserDTO getUserByLoginName(String loginName) {
 		QueryWrapper queryWrapper = new QueryWrapper ();
-		queryWrapper.eq ("a.login_name", loginName);
-		queryWrapper.eq("a.del_flag","0");
+		//判断是否是用手机号登录
+		Matcher m = pattern.matcher(loginName);
+		if (m.matches()){
+			queryWrapper.eq ("a.mobile", loginName);
+			queryWrapper.eq("a.del_flag","0");
+		} else {
+			queryWrapper.eq ("a.login_name", loginName);
+			queryWrapper.eq("a.del_flag","0");
+		}
+
+
 		UserDTO userDTO = baseMapper.get(queryWrapper);
 
+		if (null == userDTO){
+			return null;
+		}
+
 		final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
 		//获取登录ip
 		final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());

+ 1 - 0
jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/config/RestTemplateConfig.java

@@ -41,6 +41,7 @@ public class RestTemplateConfig {
             List<MediaType> mediaTypes = new ArrayList<>();
             mediaTypes.add(MediaType.TEXT_PLAIN);
             mediaTypes.add(MediaType.TEXT_HTML);
+//            mediaTypes.add(new MediaType("text", "plain", StandardCharsets.UTF_8));
             setSupportedMediaTypes(mediaTypes);
         }
     }

+ 53 - 0
jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/controller/ccpm/TestController.java

@@ -0,0 +1,53 @@
+package com.jeeplus.centerservice.controller.ccpm;
+
+import com.jeeplus.aop.demo.annotation.DemoMode;
+import com.jeeplus.aop.logging.annotation.ApiLog;
+import com.jeeplus.centerservice.utils.RestTemplateService;
+import com.jeeplus.sys.service.dto.UserDTO;
+import com.jeeplus.sys.utils.UserUtils;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: 王强
+ * @create: 2023-05-08 11:53
+ **/
+@RestController
+@RequestMapping("/test")
+public class TestController {
+
+    @Autowired
+    private RestTemplateService restTemplateService;
+
+    @DemoMode
+    @ApiLog("修改密码")
+    @RequestMapping("savePwd")
+    @ApiOperation(value = "修改密码")
+    public ResponseEntity savePwd(String newPassword) {
+        UserDTO userDTO = UserUtils.getCurrentUserDTO ( );
+        //调用服务端的修改密码接口
+//        User user = new User ( userDTO.getId ( ) );
+//        user.setPassword ( SecurityUtils.encryptPassword ( newPassword ) );
+//        user.setUpPassword("1"); // 密码修改状态改为”已修改“
+//        userService.updateById ( user );
+//        UserUtils.deleteCache ( userDTO );
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("name", userDTO.getName());
+        paramMap.put("password", newPassword);
+        paramMap.put("mobile", userDTO.getMobile());
+        String token = "";
+
+        Object res = restTemplateService.getCas("/test/update", token, null);
+
+
+        return ResponseEntity.ok ( "修改密码成功!" );
+
+    }
+}

+ 11 - 0
jeeplus-plugins/jeeplus-flowable/src/main/java/com/jeeplus/centerservice/utils/RestTemplateService.java

@@ -20,6 +20,17 @@ public class RestTemplateService {
     private RestTemplate restTemplate;
 
     /**
+     * 访问get接口 - CAS 系统
+     * @param path 接口路径
+     * @param token token
+     * @param paramMap 请求参数-路径后
+     * @return
+     */
+    public Object getCas(String path, String token, Map<String, Object> paramMap) {
+        return httpRequest(HttpMethod.GET, token, paramMap, null, Global.getConfig("CAS_PATH"), path);
+    }
+
+    /**
      * 访问post接口 - CCPM 系统
      * @param path 接口路径
      * @param token token

+ 130 - 0
jeeplus-web/src/main/java/com/jeeplus/config/MyInterceptor.java

@@ -0,0 +1,130 @@
+package com.jeeplus.config;
+
+import com.jeeplus.common.redis.RedisUtils;
+import com.jeeplus.security.config.TestCas;
+import com.jeeplus.security.jwt.TokenProvider;
+import com.jeeplus.security.util.SecurityUtils;
+import com.jeeplus.sys.constant.CacheNames;
+import com.jeeplus.sys.controller.CasRestClient;
+import com.jeeplus.sys.domain.User;
+import com.jeeplus.sys.utils.UserUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
+import org.jasig.cas.client.util.AssertionHolder;
+import org.jasig.cas.client.validation.Assertion;
+import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
+import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+import static org.jasig.cas.client.util.AbstractCasFilter.CONST_CAS_ASSERTION;
+
+/**
+ * cas验证是否登录-拦截器
+ * @author: 王强
+ * @create: 2023-04-24 15:25
+ **/
+public class MyInterceptor implements HandlerInterceptor {
+    @Autowired
+    private RedisUtils redisUtils;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        //使用SecurityContextHolder获取当前的安全上下文
+        SecurityContext securityContext = SecurityContextHolder.getContext();
+        //获取当前用户的认证详情
+        WebAuthenticationDetails details = (WebAuthenticationDetails) SecurityContextHolder.getContext()
+                .getAuthentication().getDetails();
+        //获取会话id
+        if (details != null) {
+            String sessionId = details.getSessionId();
+            System.out.println("sessionId:" + sessionId);
+        }
+
+        //从安全上下文中获取认证信息
+//        Authentication authentication = securityContext.getAuthentication();
+//        if (authentication != null && authentication.isAuthenticated()){
+//            //用户已经通过验证
+//            System.out.println("用户已经通过验证");
+//            Object principal = authentication.getPrincipal();
+//            if (principal instanceof User){
+//                User user = (User)principal;
+//                System.out.println("验证通过后的用户信息:" + user);
+//            }
+//        }
+
+
+//        if (TestCas.is) {
+////            if (null != name && name.equals("logout")){
+////                //调用前端的退出页面,退出页面默认执行退出功能
+////                response.sendRedirect("http://127.0.0.1:3000/CasLogout#/casLogout");
+////                return false;
+////            }
+////        }
+//        }
+
+        // 在请求处理之前调用
+        //重新发送一个前端的登录请求
+//        Authentication auth = SecurityUtils.getAuthentication ();
+//        String name = TestCas.name;
+//        if (null != name && name.equals("logout")){
+//            //删除用户信息
+//            HttpSession session = request.getSession();
+//            session.invalidate();
+//            UserUtils.deleteCache (UserUtils.getCurrentUserDTO () );
+//            TestCas.name = null;
+//            TestCas.urlName = null;
+//            session.invalidate();
+//            new SecurityContextLogoutHandler ( ).logout ( request, response, auth );
+//            return false;
+//        }
+
+//        String loginUrl = "http://www.casserver.com:8443/login?service=http://127.0.0.1:3000/#/casLogin";
+        // 指定需要验证的服务的URL
+        return true;
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+        // 在请求处理之后调用,但是在视图被渲染之前(Controller方法调用之后)
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        // 在请求处理之后调用,在视图被渲染之后(一定会被调用,即使发生异常)
+    }
+}

+ 6 - 1
jeeplus-web/src/main/java/com/jeeplus/config/WebConfig.java

@@ -8,6 +8,7 @@ import com.google.common.collect.Lists;
 import com.jeeplus.common.converter.StringToDateConverter;
 import com.jeeplus.common.converter.mapper.JsonMapper;
 import com.jeeplus.flowable.interceptor.FlowableHandlerInterceptor;
+import com.jeeplus.security.config.SingleSignOutHttpSessionListener;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.web.servlet.ServletRegistrationBean;
 import org.springframework.cache.annotation.EnableCaching;
@@ -50,8 +51,13 @@ public class WebConfig implements WebMvcConfigurer {
     public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(new FlowableHandlerInterceptor ())
                     .addPathPatterns("/app/**");
+        registry.addInterceptor(new MyInterceptor());
     }
 
+    @Bean
+    public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(){
+        return new SingleSignOutHttpSessionListener();
+    }
 
     @Bean
     public ServletRegistrationBean apiServlet() {
@@ -69,7 +75,6 @@ public class WebConfig implements WebMvcConfigurer {
         bean.setName("RestServlet");
         return bean;
     }
-
     /**
      * 配置后台返回数据的类型转换
      * @param converters

+ 15 - 15
jeeplus-web/src/main/resources/application-development.yml

@@ -48,7 +48,7 @@ spring:
         master:
           username: root
           password: root
-          url: jdbc:mysql://127.0.0.1:3306/assess_process_master?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://localhost:3306/assess_process_master?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai
           driver-class-name: com.mysql.cj.jdbc.Driver
 
           #oracle database settings
@@ -144,11 +144,19 @@ mybatis-plus:
 
 #是否开启 swagger,生产环境请关闭
 swagger:
-  enable: false
+  enable: true
 
 #cas服务端的地址
+#cas:
+#  server-url-prefix: https://www.cainiao.com:8443/cas
 cas:
-  server-url-prefix: http://www.casserver.com:8443
+  server_host_url: http://www.casserver.com:8443
+  server_host_login_url: http://www.casserver.com:8443/login
+  server_host_logout_url: http://www.casserver.com:8443/logout?service=http://127.0.0.1:8084/sys/casLogin
+  app_server_host_url: http://127.0.0.1:8084
+  app_login_url: /login
+  app_logout_url: /logout
+  useSingleLogout: true
 #oss配置
 config:
   accessory:
@@ -221,8 +229,8 @@ apptoken: uIJQmTwyGJ
 appsecret: 2NMBqFigKoInmd43Wohxv5aEDKiiHo
 signature: 232a44ee9ebd251d119f0a65628f678e
 
-signature_http_top: http://192.168.2.130:9182
-#signature_http_top: https://3m0m810894.goho.co
+#signature_http_top: http://192.168.2.130:9182
+signature_http_top: https://3m0m810894.goho.co
 
 #竖版模板templateId
 vertical_templateId: 2894156236229259396
@@ -235,7 +243,7 @@ company_round_seal_id_vertical: 2898043523878957918
 #公司方章
 company_parties_seal_id: 2894163220106129636
 #审定单用印流程id
-approval_category_id: 3032265972836684447
+approval_category_id: 3032955004099797473
 #报告用印流程id
 report_category_id: 2895618951099527314
 ##审定内用印流程id
@@ -245,18 +253,10 @@ approval_YC_category_id: 2932214418853044239
 #报告用印流程id(盐城)
 report_YC_category_id: 2933233458312618324
 
-#容联云
 rong_userid: 8a216da86715511501673e331c24171e
 rong_token: 3d7dc58c6a334ad6887317efbf847e41
 app_id: 8a216da86715511501673e331c741725
 template_id: 435329
 code_type: 1
 
-#其他系统的地址
-CCPM_PATH:  http://localhost:8090
-#待办中展示其他系统的流程
-#ccpm =》 13、102 报销申请、39 项目登记
-CCPM_TASK:  13,102,39
-
-#各服务引用状态 =》 (若包含,则进行获取该服务的流程信息)
-INQUIRE_STATUS: ccpm
+CAS_PATH: http://www.casserver.com:8443

+ 12 - 0
pom.xml

@@ -62,6 +62,18 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
+        <!--    security对cas支持    -->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-cas</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jasig.cas.client</groupId>
+            <artifactId>cas-client-core</artifactId>
+            <version>3.6.0</version>
+        </dependency>
+
 
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>