一、CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源。对于访问受保护资源的每个 Web 请求,CAS Client 会分析该请求的 Http 请求中是否包含 Service Ticket,如果没有,则说明当前用户尚未登录,于是将请求重定向到指定好的 CAS Server 登录地址,并传递 Service (也就是要访问的目的资源地址),以便登录成功过后转回该地址。用户在第 3 步中输入认证信息,如果登录成功,CAS Server 随机产生一个相当长度、唯一、不可伪造的 Service Ticket,并缓存以待将来验证,之后系统自动重定向到 Service 所在地址,并为客户端浏览器设置一个 Ticket Granted Cookie(TGC),CAS Client 在拿到 Service 和新产生的 Ticket 过后,在第 5,6 步中与 CAS Server 进行身份核实,以确保 Service Ticket 的合法性。

  二、在该协议中,所有与 CAS 的交互均采用 SSL 协议,确保,ST 和 TGC 的安全性。协议工作过程中会有 2 次重定向的过程,但是 CAS Client 与 CAS Server 之间进行 Ticket 验证的过程对于用户是透明的。

  三、cas客户端主要提供的是业务支持,我们在使用的时候更多是通过cas服务端来做认证支持。这里主要讲的是如何搭建cas客户端,配置的东西其实是通过spring的security来进行过滤。然后达到登录的目的,认证中主要是通过Ticket的票据进行认证的,当用户登录成功。会获取到登录的username,然后做进一步处理。

  四、服务端的部署参考:https://www.cnblogs.com/ll409546297/p/10410972.html

  五、客户端的搭建(这里服务端采用的https的方式)

  1)需要的依赖包

  1.   <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.0.0.RELEASE</version>
  5. </parent>
  6.  
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-web</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-security</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.security</groupId>
  18. <artifactId>spring-security-cas</artifactId>
  19. </dependency>
  20. </dependencies>
  1.   <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-configuration-processor</artifactId>
  5. <optional>true</optional>
  6. </dependency>
  7. </dependencies>

  说明:下面这个依赖包主要是用于配置

  2)目录结构

  

  3)cas的参数配置(cas.properties、CasProperties)

  1. cas.clientUrl=http://localhost:${server.port}
  2. cas.clientLogin=/login
  3. cas.clientLogout=/logout
  4. cas.serverUrl=https://www.casserver.com:8443/cas
  5. cas.serverLogin=/login
  6. cas.serverLogout=/logout
  7. cas.trustStorePath=cas/cas.keystore
  8. cas.trustStorePassword=changeit
  1. @PropertySource(value = "classpath:config/cas.properties")
  2. @ConfigurationProperties(prefix = "cas")
  3. public class CasProperties {
  4.  
  5. //客户端url(本机)
  6. private String clientUrl;
  7. //登录接口
  8. private String clientLogin;
  9. //登出接口
  10. private String clientLogout;
  11. //服务端url
  12. private String serverUrl;
  13. //登录接口
  14. private String serverLogin;
  15. //登出接口
  16. private String serverLogout;
  17. //证书密匙路径
  18. private String trustStorePath;
  19. //密码
  20. private String trustStorePassword;
  21.  
  22. public String getClientUrl() {
  23. return clientUrl;
  24. }
  25.  
  26. public void setClientUrl(String clientUrl) {
  27. this.clientUrl = clientUrl;
  28. }
  29.  
  30. public String getClientLogin() {
  31. return clientLogin;
  32. }
  33.  
  34. public void setClientLogin(String clientLogin) {
  35. this.clientLogin = clientLogin;
  36. }
  37.  
  38. public String getClientLogout() {
  39. return clientLogout;
  40. }
  41.  
  42. public void setClientLogout(String clientLogout) {
  43. this.clientLogout = clientLogout;
  44. }
  45.  
  46. public String getServerUrl() {
  47. return serverUrl;
  48. }
  49.  
  50. public void setServerUrl(String serverUrl) {
  51. this.serverUrl = serverUrl;
  52. }
  53.  
  54. public String getServerLogin() {
  55. return serverLogin;
  56. }
  57.  
  58. public void setServerLogin(String serverLogin) {
  59. this.serverLogin = serverLogin;
  60. }
  61.  
  62. public String getServerLogout() {
  63. return serverLogout;
  64. }
  65.  
  66. public void setServerLogout(String serverLogout) {
  67. this.serverLogout = serverLogout;
  68. }
  69.  
  70. public String getTrustStorePath() {
  71. return trustStorePath;
  72. }
  73.  
  74. public void setTrustStorePath(String trustStorePath) {
  75. this.trustStorePath = trustStorePath;
  76. }
  77.  
  78. public String getTrustStorePassword() {
  79. return trustStorePassword;
  80. }
  81.  
  82. public void setTrustStorePassword(String trustStorePassword) {
  83. this.trustStorePassword = trustStorePassword;
  84. }
  85. }

  说明:1、trustStorePath:这个主要使用的服务器上面生成的cas.keystore密钥、在服务器搭建中我们生成了cas.keystore、域名改成www.casserver.com。目的不支持直接使用IP。

     本地修改hosts:C:\Windows\System32\drivers\etc\hosts

       

     

    2、cas.keystore:服务器生成密钥,tomcat进行部署,https访问时需要的私密密钥

    3、当然可以不使用cas.keystore,通过服务器上面生成的cas.crt证书然后客户端的jdk也是可以验证通过的。

  1. keytool -import -keystore "E:\Java\jdk1.8.0_192\jre\lib\security\cacerts" -file cas.crt -alias cas -storepass changeit

  4)cas相关配置(CasConfiguration、SecurityConfiguration)

  1. @Configuration
  2. @Import(CasProperties.class)
  3. public class CasConfiguration {
  4.  
  5. //cas相关参数
  6. @Autowired
  7. private CasProperties casProperties;
  8.  
  9. //客户端的服务配置,主要用于跳转
  10. @Bean
  11. public ServiceProperties serviceProperties() {
  12. ServiceProperties serviceProperties = new ServiceProperties();
  13. //该项目的登录地址
  14. serviceProperties.setService(casProperties.getClientUrl() + casProperties.getClientLogin());
  15. serviceProperties.setAuthenticateAllArtifacts(true);
  16. return serviceProperties;
  17. }
  18.  
  19. //cas认证点
  20. @Bean
  21. public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
  22. CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
  23. //cas的登录地址
  24. casAuthenticationEntryPoint.setLoginUrl(casProperties.getServerUrl() + casProperties.getServerLogin());
  25. //入口
  26. casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
  27. return casAuthenticationEntryPoint;
  28. }
  29.  
  30. //票据
  31. @Bean
  32. public Cas30ServiceTicketValidator cas30ServiceTicketValidator() {
  33. return new Cas30ServiceTicketValidator(casProperties.getServerUrl());
  34. }
  35.  
  36. //认证支持
  37. @Bean
  38. public CasAuthenticationProvider casAuthenticationProvider(AuthDetailsService authDetailsService) {
  39. CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
  40. casAuthenticationProvider.setKey("client1");
  41. casAuthenticationProvider.setServiceProperties(serviceProperties());
  42. casAuthenticationProvider.setTicketValidator(cas30ServiceTicketValidator());
  43. //本地登录后的操作,走security体系
  44. casAuthenticationProvider.setUserDetailsService(authDetailsService);
  45. //这里也可以使用setAuthenticationUserDetailsService管理
  46. //casAuthenticationProvider.setAuthenticationUserDetailsService();
  47. return casAuthenticationProvider;
  48. }
  49.  
  50. //单点登录过滤
  51. @Bean
  52. public SingleSignOutFilter singleSignOutFilter() {
  53. SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
  54. singleSignOutFilter.setCasServerUrlPrefix(casProperties.getServerUrl());
  55. singleSignOutFilter.setIgnoreInitConfiguration(true);
  56. return singleSignOutFilter;
  57. }
  58.  
  59. //登出过滤
  60. @Bean
  61. public LogoutFilter logoutFilter() {
  62. //重定向地址
  63. String logoutRedirectPath = casProperties.getServerUrl() + casProperties.getServerLogout() + "?service=" + casProperties.getClientUrl();
  64. LogoutFilter logoutFilter = new LogoutFilter(logoutRedirectPath, new SecurityContextLogoutHandler());
  65. //登出接口
  66. logoutFilter.setFilterProcessesUrl(casProperties.getServerLogout());
  67. return logoutFilter;
  68. }
  69.  
  70. }
  1. @Configuration
  2. @EnableWebSecurity
  3. @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
  4. @Import(CasProperties.class)
  5. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  6.  
  7. //认证
  8. @Autowired
  9. private CasAuthenticationProvider authenticationProvider;
  10.  
  11. //认证点
  12. @Autowired
  13. private CasAuthenticationEntryPoint authenticationEntryPoint;
  14.  
  15. //登出过滤
  16. @Autowired
  17. private LogoutFilter logoutFilter;
  18.  
  19. //单点登出
  20. @Autowired
  21. private SingleSignOutFilter singleSignOutFilter;
  22.  
  23. //cas配置
  24. @Autowired
  25. private CasProperties casProperties;
  26.  
  27. @Override
  28. protected void configure(HttpSecurity http) throws Exception {
  29. http
  30. .csrf().disable()
  31. .exceptionHandling()
  32. .authenticationEntryPoint(authenticationEntryPoint)
  33. .and()
  34. .authorizeRequests()
  35. .anyRequest().authenticated()
  36. .and()
  37. //添加认证过滤(这里我遇到一个坑,如果通过注入方式加入,会出现循环依赖问题)
  38. .addFilter(casAuthenticationFilter())
  39. //登出过滤
  40. .addFilterBefore(logoutFilter, LogoutFilter.class)
  41. //单点登出过滤
  42. .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class);
  43. }
  44.  
  45. @Override
  46. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  47. //认证方式
  48. auth.authenticationProvider(authenticationProvider);
  49. }
  50.  
  51. @Bean
  52. public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
  53. //过滤器配置
  54. CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
  55. //使用security的认证管理
  56. casAuthenticationFilter.setAuthenticationManager(authenticationManager());
  57. //拦截登录接口
  58. casAuthenticationFilter.setFilterProcessesUrl(casProperties.getClientLogin());
  59. return casAuthenticationFilter;
  60. }
  61. }

  5)登录后的username处理(AuthDetailsService)

  1. @Service
  2. public class AuthDetailsService implements UserDetailsService {
  3.  
  4. @Override
  5. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  6. if (username == null){
  7. throw new UsernameNotFoundException("用户不存在!");
  8. }
  9. List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
  10. simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ADMIN"));
  11. return new org.springframework.security.core.userdetails.User(username, username, simpleGrantedAuthorities);
  12. }
  13. }

  说明:这里只是简单处理,实际可以自己绑定用户处理

  6)https处理(CasIinitTask)

  1. @Component
  2. @Import(CasProperties.class)
  3. public class CasIinitTask {
  4.  
  5. @Autowired
  6. private CasProperties casProperties;
  7.  
  8. @PostConstruct
  9. public void loadKeystore() throws IOException {
  10. //如果使用https,则必须加入密钥
  11. Assert.isTrue(!(casProperties.getServerUrl().startsWith("https") && casProperties.getTrustStorePath() == null),
  12. "trustStorePath must not null to configuration https");
  13. //密钥
  14. if (!StringUtils.isEmpty(casProperties.getTrustStorePath())) {
  15. Resource resource = new ClassPathResource(casProperties.getTrustStorePath());
  16. System.setProperty("javax.net.ssl.trustStore", resource.getFile().getAbsolutePath());
  17. }
  18. //有可能密码的情况
  19. if (StringUtils.isEmpty(casProperties.getTrustStorePassword())) {
  20. System.setProperty("javax.net.ssl.trustStorePassword", casProperties.getTrustStorePassword());
  21. }
  22. }
  23. }

  7)启动项目测试:

  六、源码:https://github.com/lilin409546297/springboot-cas

  七、这里只是简单的搭建过程,实际cas还需要做二次开发。相比于cas和oauth2我个人更加喜欢oauth2,个人看法。

springboot之cas客户端的更多相关文章

  1. CAS学习笔记三:SpringBoot自动配置与手动配置过滤器方式集成CAS客户端

    本文目标 基于SpringBoot + Maven 分别使用自动配置与手动配置过滤器方式集成CAS客户端. 需要提前搭建 CAS 服务端,参考 https://www.cnblogs.com/hell ...

  2. Springboot security cas整合方案-实践篇

    承接前文Springboot security cas整合方案-原理篇,请在理解原理的情况下再查看实践篇 maven环境 <dependency> <groupId>org.s ...

  3. Springboot security cas整合方案-原理篇

    前言:网络中关于Spring security整合cas的方案有很多例,对于Springboot security整合cas方案则比较少,且有些仿制下来运行也有些错误,所以博主在此篇详细的分析cas原 ...

  4. CAS5.3服务器搭建及SpringBoot整合CAS实现单点登录

    1.1 什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的 ...

  5. CAS客户端服务器端配置步骤

    来自我的个人网站:http://lkf.22web.org/ cas介绍: CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 ...

  6. 如何利用tomcat和cas实现单点登录(2):配置cas数据库验证和cas客户端配置

    接(1),上一篇主要讲述了tomcat和cas server端的部署. 接下来主要还有两个步骤. 注意:为了开启两个tomcat,要把直接配置的tomcat的环境变量取消!!!!!!!!!! 客户端配 ...

  7. 配置php的CAS客户端

    1.下载安装xmapp 2.开启Apache服务. 3.下载php的CAS客户端源码包(我使用的是CAS-1.2.0.tgz),解压到xmap的htdocs目录下(D:\xmapp\htdocs),进 ...

  8. cas sso单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

    转:http://blog.csdn.net/ae6623/article/details/8848107 1)PPT流程图:ppt下载:http://pan.baidu.com/s/1o7KIlom ...

  9. Springboot security cas源码陶冶-ExceptionTranslationFilter

    拦截关键的两个异常,对异常进行处理.主要应用异常则跳转至cas服务端登录页面 ExceptionTranslationFilter#doFilter-逻辑入口 具体操作逻辑如下 public void ...

随机推荐

  1. 解析UIControl

    解析UIControl 从下图可以看出,UIControl继承自UIView,添加了响应事件功能. UIButton之所以能响应各种各样的事件是因为继承自UIControl 使用UIControl可以 ...

  2. 转载、Python的编码处理(二)

    以下转自于:wklken的博客,写的非常好的一段有关编码的总结. Python-进阶-编码处理小结 整理下python编码相关的内容 注意: 以下讨论为Python2.x版本, Py3k的待尝试 开始 ...

  3. 铁乐学Python_day03-字符串常用操作方法

    文:铁乐与猫 2018-3-20 1)字符串首个字母大写,其它字母也会转换成小写: S.capitalize() -> str 记忆方法:capital(大写字母) def capitalize ...

  4. 深入浅出SharePoint2013——安装SharePoint2013

    在这个页面的底部可以通过相应链接下载Sharepoint Server安装文件  https://technet.microsoft.com/en-us/library/cc262788.aspx

  5. September 19th 2017 Week 38th Tuesday

    Live boldly. Push yourself. Don't settle. 勇敢生活,突破自我,永不设限! Don't indulge in the past, whether it was ...

  6. CR与LF

    CR与LF CR(carriage return),中文名称"回车":LF(line feed),中文名称"换行".无论是初学编程的小白还是入行十年的资深,总会 ...

  7. 利用Jquey.hover来实现 鼠标移入出现删除按钮,鼠标移出删除消失

    Html代码 <div class="box"><div class="bmbox" onclick="$('.box:first' ...

  8. arcgis 10.1 导入数据到oracle 发布地图服务

    机器配置说明 数据库服务器 系统:linux 软件:oracle 11G 64位 Arcgis server服务器 系统:win7 专业版 软件:arcgis server 10.1.win64_11 ...

  9. 【洛谷】【线段树】P1886 滑动窗口

    [题目描述:] 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. [输入格式:] 输入一共 ...

  10. 怎样批量提取JPG照片的文件名

    用批处理做吧, @echo off dir /a-d /b >./list.txt 把上面两句代码用记事本保存为“list.bat”(不要引号) 然后把这个文件放到你要提取文件名的文件夹里,就是 ...