zmzmmf 2020-02-09
先说一个需求场景,比如:一个企业的内部有N多个子系统,每个子系统都有一套自己的用户名和密码,那么企业的员工要登录N个子系统,这样一个员工 就要记住N个用户名和密码,就算各个子系统的用户名和密码都是统一的,登录每个子系统都要输入用户名和密码进行登录也是一个繁琐的操作过程,那么单点登录功能由此便应运而生了。
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
这里直接说CAS整体架构是因为这不是一个入门教程,我已经默认你知道什么是SSO、什么是CAS,以及你已经装好了开发工具IDEA和Java环境Jdk1.8,并且你也知道什么是Web容器,知道Tomcat8.5+该从哪下载并启动部署,你也知道什么是Maven项目该怎么引入相关的jar包等等,所以如果你不具备以上这些知识,那么CAS服务端的学习我建议你还是先不要开始,弄清楚前面的知识点,才能畅通无阻的学习CAS服务端。
好了,这里先放架构图:

现在来讲解这个架构图:
首先搭建好CAS服务端后,服务端会自定义一个数据库和用户表,用户表中存放的是用户名和密码,通过访问子系统的URL地址,如果CAS系统判定你没有登录,就会将URL重定向到CAS的服务端登录界面,用户通过输入用户数据库的用户名和密码来进行登录,待登录成功后,CAS服务端会给CAS客户端(子系统)发送登录的用户名,CAS客户端接到用户名后,会从CAS客户端的用户表中寻找对应用户名的userid,并通过该userid获取到该名用户在CAS客户端的相关权限。
我们还可以基于CAS服务端配置的用户数据库做一个用户管理界面,该界面可以对CAS服务端的用户进行一些基本的业务操作,比如新增、修改、删除等,新增用户的时候,需要同时在各个子系统的用户表中插入该用户的相关信息,然后各个子系统的管理员就可以通过子系统的角色权限设置,给该用户配置相关的角色权限了。
讲了这么多,现在开始进入正题,我们要实现我们的目的首先要做的就是安装CAS服务端,现在网上的很多Springboot整合CAS的教程基本上都是只讲客户端的配置,看完之后云里雾里的,所以我这个教程要从CAS的服务端开始讲起,如果你们公司有人专门搭建CAS服务端,那就可以跳过本篇教程继续下一篇了。
搭建Overlay项目
将项目下好后解压缩并放入我们的工作空间,然后打开IDEA,然后选择File–Open打开我们项目所在路径,然后我们只要静静的等待Maven将项目构筑好就可以了。这时你看到的项目是这个样子的:

这是我的项目,你的项目中并没有src目录和target目录,src目录是用户自己建立的,至于为什么后边会讲,target目录是导出war时才出现的,新导入的项目是没有的。
制成可用的CAS服务端
现在的CAS服务端基本上是不可用的,为什么说基本上呢?因为如果你现在讲项目打成war包,并将它部署到Tomcat中去后是可以启动服务的,并且访问本地地址:http://localhost:8080/cas/login还可以看到如下界面:

使用 默认账号:casuser 默认密码:Mellon还可以登录成功,不过这个CAS服务端目前并没有什么卵用,只是可以看看而已。
这两个红色警告,一个是说没有使用Https,另一个是说你只有一个静态的权限,一个写死的用户,其实就是告诉你现在的服务端是不安全的。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | <?xml version="1.0" encoding="UTF-8"?>< 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> <groupId>org.apereo.cas</groupId> <artifactId>cas-overlay</artifactId> <packaging>war</packaging> <version>1.0</version> <build> <plugins> <plugin> <groupId>com.rimerosolutions.maven.plugins</groupId> <artifactId>wrapper-maven-plugin</artifactId> <version>0.0.4</version> <configuration> <verifyDownload>true</verifyDownload> <checksumAlgorithm>MD5</checksumAlgorithm> </configuration> </plugin>--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${springboot.version}</version> <configuration> <mainClass>org.springframework.boot.loader.WarLauncher</mainClass> <addResources>true</addResources> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <warName>cas</warName> <failOnMissingWebXml>false</failOnMissingWebXml> <recompressZippedFiles>false</recompressZippedFiles> <archive> <compress>false</compress> <manifestFile>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MF </manifestFile> </archive> <overlays> <overlay> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp${app.server}</artifactId> </overlay> </overlays> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> </plugin> </plugins> <finalName>cas</finalName> </build> <dependencies> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp${app.server}</artifactId> <version>${cas.version}</version> <type>war</type> <scope>runtime</scope> </dependency> <!--第二步:引入数据库认证相关 start--> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>org.apereo.cas</groupId>大专栏 Springboot集成Shiro和Cas实现单点登录(服务端篇CAS5)"> <artifactId>cas-server-support-jdbc-drivers</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version> </dependency> </dependencies> <properties> <cas.version>5.1.4</cas.version> <springboot.version>1.5.3.RELEASE</springboot.version> <!-- app.server could be -jetty, -undertow, -tomcat, or blank if you plan to provide appserver --> <app.server>-tomcat</app.server> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <repositories> <repository> <id>sonatype-releases</id> <url>http://oss.sonatype.org/content/repositories/releases/</url> <snapshots> <enabled>false</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> <repository> <id>sonatype-snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>false</enabled> </releases> </repository> <repository> <id>shibboleth-releases</id> <url>https://build.shibboleth.net/nexus/content/repositories/releases</url> </repository> <repository> <id>spring-milestones</id> <url>https://repo.spring.io/milestone</url> </repository> </repositories> <!--第三步:注释掉无用的组件 <profiles> <profile> <activation> <activeByDefault>false</activeByDefault> </activation> <id>pgp</id> <build> <plugins> <plugin> <groupId>com.github.s4u.plugins</groupId> <artifactId>pgpverify-maven-plugin</artifactId> <version>1.1.0</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> <configuration> <pgpKeyServer>hkp://pool.sks-keyservers.net</pgpKeyServer> <pgpKeysCachePath>${settings.localRepository}/pgpkeys-cache</pgpKeysCachePath> <scope>test</scope> <verifyPomFiles>true</verifyPomFiles> <failNoSignature>false</failNoSignature> </configuration> </plugin> </plugins> </build> </profile> </profiles>--></> |
1 | #STEP 3 在TOMCAT8.5中跑一个模板然后将其war包中解压出来的的application.properties复制出来,放到手动创建的src下的resources里面
##
# CAS Server Context Configuration
#z
server.context-path=/cas
server.port=9092
#STEP 5添加认证服务
cas.serviceRegistry.initFromJson=true
#STEP 4签发证书,如果是用spring boot之类嵌入式的容器,则需要改这里的配置,如果是直接部在tomcat中,则需要把tomcat改成https的
#server.ssl.key-store=file:/etc/cas/thekeystore
#server.ssl.key-store-password=changeit
#server.ssl.key-password=changeit
# server.ssl.ciphers=
# server.ssl.client-auth=
# server.ssl.enabled=
# server.ssl.key-alias=
# server.ssl.key-store-provider=
# server.ssl.key-store-type=
# server.ssl.protocol=
# server.ssl.trust-store=
# server.ssl.trust-store-password=
# server.ssl.trust-store-provider=
# server.ssl.trust-store-type=
#server.max-http-header-size=2097152
#server.use-forward-headers=true
#server.connection-timeout=20000
#server.error.include-stacktrace=NEVER
#server.tomcat.max-http-post-size=2097152
#server.tomcat.basedir=build/tomcat
#server.tomcat.accesslog.enabled=true
#server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
#server.tomcat.accesslog.suffix=.log
#server.tomcat.max-threads=10
#server.tomcat.port-header=X-Forwarded-Port
#server.tomcat.protocol-header=X-Forwarded-Proto
#server.tomcat.protocol-header-https-value=https
#server.tomcat.remote-ip-header=X-FORWARDED-FOR
#server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
##
# CAS Cloud Bus Configuration
#
spring.cloud.bus.enabled=false
# spring.cloud.bus.refresh.enabled=true
# spring.cloud.bus.env.enabled=true
# spring.cloud.bus.destination=CasCloudBus
# spring.cloud.bus.ack.enabled=true
endpoints.enabled=false
endpoints.sensitive=true
endpoints.restart.enabled=false
endpoints.shutdown.enabled=false
management.security.enabled=true
management.security.roles=ACTUATOR,ADMIN
management.security.sessions=if_required
management.context-path=/status
management.add-application-context-header=false
security.basic.authorize-mode=role
security.basic.enabled=false
security.basic.path=/cas/status/**
##
# CAS Web Application Session Configuration
#
server.session.timeout=300
server.session.cookie.http-only=true
server.session.tracking-modes=COOKIE
##
# CAS Thymeleaf View Configuration
#
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML
##
# CAS Log4j Configuration
#
# logging.config=file:/etc/cas/log4j2.xml
server.context-parameters.isLog4jAutoInitializationDisabled=true
##
# CAS AspectJ Configuration
#
spring.aop.auto=true
spring.aop.proxy-target-class=true
##
# CAS Authentication Credentials
#
#STEP4 注释掉写死的用户 改用jdbc的用户 START
#cas.authn.accept.users=casuser::Mellon
cas.authn.jdbc.query[0].sql=select * from s_user where username=?
cas.authn.jdbc.query[0].healthQuery=
cas.authn.jdbc.query[0].isolateInternalQueries=false
cas.authn.jdbc.query[0].url=jdbc:mysql://172.18.18.25:3306/pa_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.jdbc.query[0].failFast=true
cas.authn.jdbc.query[0].isolationLevelName=ISOLATION_READ_COMMITTED
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
cas.authn.jdbc.query[0].leakThreshold=10
cas.authn.jdbc.query[0].propagationBehaviorName=PROPAGATION_REQUIRED
cas.authn.jdbc.query[0].batchSize=1
cas.authn.jdbc.query[0].user=root
#cas.authn.jdbc.query[0].ddlAuto=create-drop
cas.authn.jdbc.query[0].maxAgeDays=180
cas.authn.jdbc.query[0].password=dhcc
cas.authn.jdbc.query[0].autocommit=false
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
cas.authn.jdbc.query[0].idleTimeout=5000
# cas.authn.jdbc.query[0].credentialCriteria=
# cas.authn.jdbc.query[0].name=
# cas.authn.jdbc.query[0].order=0
# cas.authn.jdbc.query[0].dataSourceName=
# cas.authn.jdbc.query[0].dataSourceProxy=false
cas.authn.jdbc.query[0].fieldPassword=password
# cas.authn.jdbc.query[0].fieldExpired=
# cas.authn.jdbc.query[0].fieldDisabled=
# cas.authn.jdbc.query[0].principalAttributeList=sn,cn:commonName,givenName
#cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
#cas.authn.jdbc.query[0].passwordEncoder.type=com.example.CustomPasswordEncoder
#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
#cas.authn.jdbc.query[0].passwordEncoder.secret=
#cas.authn.jdbc.query[0].passwordEncoder.strength=16
# cas.authn.jdbc.query[0].principalTransformation.suffix=
# cas.authn.jdbc.query[0].principalTransformation.caseConversion=NONE|UPPERCASE|LOWERCASE
# cas.authn.jdbc.query[0].principalTransformation.prefix=
# STEP4 END
##
# CAS Delegated Authentication
#
#cas.authn.pac4j.bitbucket.clientName=Bitbucket
#cas.authn.pac4j.dropbox.clientName=Dropbox
#cas.authn.pac4j.facebook.clientName=Facebook
#cas.authn.pac4j.foursquare.clientName=Foursquare
#cas.authn.pac4j.github.clientName=Github
#cas.authn.pac4j.google.clientName=Google
#cas.authn.pac4j.linkedIn.clientName=LinkedIn
#cas.authn.pac4j.paypal.clientName=PayPal
#cas.authn.pac4j.twitter.clientName=Twitter
#cas.authn.pac4j.yahoo.clientName=Yahoo
#cas.authn.pac4j.windowsLive.clientName=Windows Live
#cas.authn.pac4j.wordpress.clientName=WordPress
#多属性
cas.authn.attributeRepository.jdbc[0].singleRow=true
cas.authn.attributeRepository.jdbc[0].order=0
cas.authn.attributeRepository.jdbc[0].url=jdbc:mysql://172.18.18.25:3306/pa_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.attributeRepository.jdbc[0].username=username
cas.authn.attributeRepository.jdbc[0].user=root
cas.authn.attributeRepository.jdbc[0].password=dhcc
cas.authn.attributeRepository.jdbc[0].sql=select * from s_user where {0}
cas.authn.attributeRepository.jdbc[0].dialect=org.hibernate.dialect.MySQLDialect
cas.authn.attributeRepository.jdbc[0].ddlAuto=none
cas.authn.attributeRepository.jdbc[0].driverClass=com.mysql.jdbc.Driver
cas.authn.attributeRepository.jdbc[0].leakThreshold=10
cas.authn.attributeRepository.jdbc[0].propagationBehaviorName=PROPAGATION_REQUIRED
cas.authn.attributeRepository.jdbc[0].batchSize=1
cas.authn.attributeRepository.jdbc[0].healthQuery=SELECT 1
cas.authn.attributeRepository.jdbc[0].failFast=trueyeshi
#http访问
cas.tgc.secure=false |
看上面的配置文件你会发现我配置了mysql的jdbc连接请求,其实就是为了给CAS服务端配置用户名和密码验证的,你自己做的话,需要在你的数据库中创建一个数据库空间和一张用户表,并且保证该表中最少有三个字段:id,username和password,这个配置文件中写的是我的测试服务器的配置,你要改成自己的哦。
这里有几个点要注意下:
cas.authn.accept.users=casuser::Mellon这个配置记得删掉,这就是那个写死的用户
cas.authn.jdbc.query[0]这些配置就是数据库验证相关的内容
在cas.authn.jdbc.query[0].sql中,程序会把你登录时输入的用户名作为参数传进去
cas.authn.jdbc.query[0].fieldPassword则是指明那一列对应的是你输入的密码,目前没有做MD5
如果使用http访问 必须加入 cas.tgc.secure=false 否则登录状态不能共享。
请在系统的C:WINDOWSSystem32driversetchosts 文件中加入:
127.0.0.1 com.dhcc.cas
这么做的目的是将这个IP地址指向这个域名,其实本意是为了https访问做的工作,如果想知道其目的可以查看cas https访问相关的资料,本教程里就不再细说了。
这里可能不好理解,我先来讲一个我遇到的问题,你就可以理解了:
配置好CAS的客户端后,我就开始测试我的客户端子系统,在浏览器中输入我的子系统项目地址:
http://com.dhcc.cas:9093
后由于我的子系统的配置,访问界面会重定向到
http://com.dhcc.cas:9092/cas/login?service:http://com.dhcc.cas:9093/
但是这个界面理论上来说应该是跳转到CAS服务端的登录界面的,可是我的这个路径却无法跳转,
并展示如下界面:

我百思不得其解,尝试了各种方法也不行,直到我发现了将路径改为:
http://com.dhcc.cas:9092/cas/login?service=https://com.dhcc.cas:9093/
界面会自动跳转到CAS服务端的登录界面,这时我才开始回忆起CAS服务端是不是哪里我没有配置对,于是我在网上查资料才知道CAS4.2以上光加入cas.tgc.secure=false 这个参数配置是不够的,还要对HTTPSandIMAPS-10000001.json这个文件中进行修改,大家可能会问了,我怎么没看到这个文件?
因为默认的项目架构是没有这个文件的,我们要将导出的war包解压,然后在WEB-INFclassesservices这个路径下找到这个文件,然后在我们的项目中的resources目录下再新建一个services目录,并将该文件拷贝到这个路径下即可。
现在你的项目架构应该是这个样子的:

引入这个文件肯定是为了修改它,我们可以看到这个json中有行代码,其实是个正则表达式:
1 | "serviceId" : "^(https|imaps)://.*" |
了解json的都知道,这里其实是说serviceId的值是所有带https和imaps的url请求都会被当成已经注册的服务,我们只要将它改成下面这样就可以了:
1 | "serviceId" : "^(https|imaps|http)://.*" |
这样我们就可以安心的使用CAS的http请求服务了。
至此,我们的CAS服务端基本上就搭建好了,只要将它打成war包,并放到tomcat中启动起来,便可以作为们的单点登录的服务端使用了。
这里需要注意一下几点:
只要你的服务端可以正常启用,你就成功了一半了,下一篇我们就开始讲解CAS客户端的配置了。