基于CAS的WEB单点登录(sso)服务端及其tomcat/nginx https配置

一、关于SSO单点登录

单点登录sso的实现常见的有Oauth2(当前主流,较复杂)和CAS(Center Authentication Server),它们的区别。这里先研究一把apereo 实现的CAS SSO。

二、CAS基本原理,参考https://www.jianshu.com/p/b7de8e4cf217

    

 

  1. 访问服务:SSO 客户端发送请求访问应用系统提供的服务资源。
  2. 定向认证:SSO 客户端会重定向用户请求到 SSO 服务器。
  3. 用户认证:用户身份认证。
  4. 发放票据: SSO 服务器会产生一个随机的 Service Ticket 。
  5. 验证票据: SSO 服务器验证票据 ST 的合法性,验证通过后,允许客户端访问服务。(每次请求都会到server端验证ST)
  6. 传输用户信息: SSO 服务器验证票据通过后,传输用户认证结果信息给客户端。

CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个 Web 请求,同时, CAS Client 会分析 HTTP 请求中是否包含请求 Service Ticket( ST 上图中的 Ticket) ,如果没有,则说明该用户是没有经过认证的;于是 CAS Client 会重定向用户请求到 CAS Server ( Step 2 ),并传递 Service (要访问的目的资源地址)。 Step 3 是用户认证过程,如果用户提供了正确的 Credentials , CAS Server 随机产生一个相当长度、唯一、不可伪造的 Service Ticket ,并缓存以待将来验证,并且重定向用户到 Service 所在地址(附带刚才产生的 Service Ticket ) , 并为客户端浏览器设置一个 Ticket Granted Cookie ( TGC ) ; CAS Client 在拿到 Service 和新产生的 Ticket 过后,在 Step 5 和 Step6 中与 CAS Server 进行身份核实,以确保 Service Ticket 的合法性。在该协议中,所有与 CAS Server 的交互均采用 SSL 协议,以确保 ST 和 TGC 的安全性。协议工作过程中会有 2 次重定向 的过程。但是 CAS Client 与 CAS Server 之间进行 Ticket 验证的过程对于用户是透明的(使用 HttpsURLConnection )。

应用系统将登录请求转给认证中心,这个很好解决,我们一个HTTP重定向即可实现。现在的问题是,用户在认证中心登录后,认证中心如何将消息转回给该系统?这是在单web系统中不存在的问题。我们知道HTTP协议传递消息只能通过请求参数方式或cookie方式,cookie跨域问题不能解决,我们只能通过URL请求参数。我们可以将认证通过消息做成一个令牌(token)再利用HTTP重定向传递给应用系统。但现在的关键是:该系统如何判断这个令牌的真伪?如果判断这个令牌确实是由认证中心发出的,且是有效的?我们还需要应用系统和认证中心之间再来个直接通信,来验证这个令牌确实是认证中心发出的,且是有效的。由于应用系统和认证中心是属于服务端之间的通信,不经过用户浏览器,相对是安全的。

假如现在应用集群中又两个系统A、B。当客户首次登录A系统的时候,流程如下:

  1. 用户浏览器访问系统A需登录受限资源。
  2. 系统A发现该请求需要登录,将请求重定向到认证中心,进行登录。
  3. 认证中心呈现登录页面,用户登录,登录成功后,认证中心重定向请求到系统A,并附上认证通过令牌。
  4. 系统A与认证中心通信,验证令牌有效,证明用户已登录。
  5. 系统A将受限资源返给用户。

已登录用户首次访问应用群中系统B时:

  1. 浏览器访问另一应用B需登录受限资源。
  2. 系统B发现该请求需要登录,将请求重定向到认证中心,进行登录。
  3. 认证中心发现已经登录,即重定向请求响应到系统B,附带上认证令牌。
  4. 系统B与认证中心通信,验证令牌有效,证明用户已登录。
  5. 系统B将受限资源返回给客户端。

 

三、认证服务端部署

因为6.X版本需要JDK11+,故使用较旧的5.3(JDK8+)版本,地址https://github.com/apereo/cas-overlay-template/tree/5.3,clone或下载zip,进入项目根目录mvm clean package打成一个cas.war包。放到Tomcat webapp并启动tomcat,浏览器访问http://192.168.154.134:8080/cas/login ,页面稍微改一下,加上公司logo等就可以了

四、https配置(Tomcat、Nginx)

tomcat直接支持https,参考https://www.cnblogs.com/wanghaoyuhappy/p/5267702.html

#生成证书,密码123456
keytool -genkeypair -alias "futurecloud" -keyalg "RSA" -keystore "/etc/cas/tomcat.keystore"

tomcat server.xml配置https

<Connector
    protocol="org.apache.coyote.http11.Http11NioProtocol" 
    port="8443" maxThreads="200" 
    scheme="https" secure="true" SSLEnabled="true" 
    keystoreFile="/etc/cas/tomcat.keystore" keystorePass="123456" 
    clientAuth="false" sslProtocol="TLS"/>

企业中一般配置Nginx支持https进行反向代理

检查Nginx是否已安装ssl模块

[root@master nginx-1.7.4]# nginx -V
nginx version: nginx/1.7.4
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

如果没有

#重新配置
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
#重新编译make,不需要make  install安装。否则会覆盖原有的模块

或重新安装Nginx (docker安装参考

wget http://nginx.org/download/nginx-1.7.4.tar.gz

tar -zxvf nginx-1.7.4.tar.gz
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-
http_ssl_module

make

make install

nginx -V

nginx -s quit 

nginx -c /usr/XXX/nginx.conf 如重新安装最好带配置启动,避免用错配置

通过openssl生成证书

1)设置server.key,这里需要设置两遍密码123456:

openssl genrsa -des3 -out server.key 1024

2)不填或随便填:

openssl req -new -key server.key -out server.csr

3) 写RSA秘钥(这里也要求输入之前设置的密码):

openssl rsa -in server.key -out server_nopwd.key

4)生成私钥:

openssl x509 -req -days 365 -in server.csr -signkey server_nopwd.key -out server.crt

 Nginx使用生成的证书配置cas server端https访问

server {

    listen    81;       #侦听80端口,如果强制所有的访问都必须是HTTPs的,这行需要注销掉
    listen    443 ssl;
    server_name  localhost; #域名
    #ssl on;   ####如果强制HTTPs访问,这行要打开
    ssl_certificate /etc/cas/server.crt;
    ssl_certificate_key /etc/cas/server_nopwd.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_protocols  SSLv2 SSLv3 TLSv1.2;    # 指定密码为openssl支持的格式
    ssl_ciphers  HIGH:!aNULL:!MD5;  # 密码加密方式
    ssl_prefer_server_ciphers  on;  # 依赖SSLv3和TLSv1协议的服务器密码将优先于客户端密码

   location / {
            #root   html;
            #index  index.html index.htm;
          proxy_pass http://localhost:8080; #tomcat就没必要配置https了
        }
}

页面访问,application.properties内置用户密码casuser/Mellon

五、整合MySQL查询用户登录

在pom.xml中profile的id = default的dependencies中添加依赖

<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-support-jdbc</artifactId>
    <version>${cas.version}</version>
</dependency>
<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-support-jdbc-drivers</artifactId>
    <version>${cas.version}</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
</dependency>

application.properties配置数据库连接

cas.authn.jdbc.query[0].url=jdbc:mysql://4X.XX.XX.18:3306/cas?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
cas.authn.jdbc.query[0].user=root
cas.authn.jdbc.query[0].password=XXXX
cas.authn.jdbc.query[0].sql=select * from cas_user where username=?
cas.authn.jdbc.query[0].fieldPassword=password
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver

表结构与数据

CREATE TABLE `cas_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT '',
  `email` varchar(30) DEFAULT NULL,
  `telephone` varchar(11) DEFAULT NULL,
  UNIQUE KEY `id` (`id`) USING HASH
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `cas_user` VALUES (1, 'jwolf', 'jwolf', NULL, NULL);

新用户jwolf/jwolf登录

1,tomcat8的配置: 1.1修改tomcat8.x/conf/context.xml的配置如下: <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- The contents of this file will be loaded for each web application --> <Context> <!-- Default set of monitored resources. If one of these changes, the --> <!-- web application will be reloaded. --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> <Resources cachingAllowed="true" cacheMaxSize="100000" /> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:127.0.0.1:11211" username="root" password="" sticky="false" sessionBackupAsync="false" lockingMode="uriPattern:/path1|/path2" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" /> --> <Resources cachingAllowed="true" cacheMaxSize="100000" /> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:127.0.0.1:11211" username="root" password="" sticky="false" sessionBackupAsync="false" lockingMode="uriPattern:/path1|/path2" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" sessionBackupTimeout="18000" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" copyCollectionsForSerialization="false" /> </Context> 1.2添加memcached如下依赖的jar包到tomcat8.x/lib/: asm-5.1.jar couchbase-client-1.4.12.jar javolution-5.5.1.jar kryo-4.0.0.jar kryo-serializers-0.38.jar memcached-session-manager-2.0.0.jar memcached-session-manager-tc8-2.0.0.jar minlog-1.3.jar msm-javolution-serializer-2.0.0.jar msm-kryo-serializer-2.0.0.jar msm-xstream-serializer-2.0.0.jar objenesis-2.1.jar reflectasm-1.09.jar spymemcached-2.12.1.jar 2,nginx配置: #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; client_header_timeout 3m; client_body_timeout 3m; send_timeout 3m; sendfile on; tcp_nopush on; tcp_nodelay on; #keepalive_timeout 0; keepalive_timeout 65; gzip on; #设定负载均衡的服务器列表 upstream 127.0.0.1 { #设定负载均衡的服务器列表 #ip_hash; #同一机器在多网情况下,路由切换,ip可能不同 #weigth参数表示权值,权值越高被分配到的几率越大 server 127.0.0.1:8085 weight=1 max_fails=20 fail_timeout=600s; server 127.0.0.1:8086 weight=1 max_fails=20 fail_timeout=600s; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; server_name localhost; charset UTF-8; #设定本虚拟主机的访问日志 access_log logs/host.access.log main; #对 "/" 所有应用启用负载均衡 location / { proxy_pass http://127.0.0.1; #保留用户真实信息 proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; index index.html index.htm index.aspx; } #对 "/Dossm3RabbitMQConsumer/" 启用负载均衡 location /Dossm3RabbitMQConsumer/ { proxy_pass http://localhost:8086; #保留用户真实信息 proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; index index.html index.htm index.aspx; } } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} } 3,cas配置(): 3.1 修改/CAS/WEB-INF/spring-configuration/ticketRegistry.xml <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to Jasig under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Jasig licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at the following location: http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <description> Configuration for the default TicketRegistry which stores the tickets in-memory and cleans them out as specified intervals. </description> <!-- memcached 配置开始 --> <!-- Ticket Registry --> <bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.MemCacheTicketRegistry"> <constructor-arg index="0"> <bean class="net.spy.memcached.spring.MemcachedClientFactoryBean" p:servers="127.0.0.1:11211" p:protocol="BINARY" p:locatorType="ARRAY_MOD" p:failureMode="Redistribute" p:transcoder-ref="serialTranscoder"> <property name="hashAlg"> <util:constant static-field="net.spy.memcached.DefaultHashAlgorithm.FNV1A_64_HASH" /> </property> </bean> </constructor-arg> <!-- TGT timeout in seconds --> <constructor-arg index="1" value="36000" /> <!-- ST timeout in seconds --> <constructor-arg index="2" value="2" /> </bean> <bean id="serialTranscoder" class="net.spy.memcached.transcoders.SerializingTranscoder" p:compressionThreshold="2048" /> <!-- memcached 配置结束 --> <!--Quartz --> <!-- 默认配置开始 --> <!-- Ticket Registry --> <!-- <bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" />--> <!-- TICKET REGISTRY CLEANER --> <!-- <bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner" p:ticketRegistry-ref="ticketRegistry" p:logoutManager-ref="logoutManager" /> <bean id="jobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" p:targetObject-ref="ticketRegistryCleaner" p:targetMethod="clean" /> <bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean" p:jobDetail-ref="jobDetailTicketRegistryCleaner" p:startDelay="200000" p:repeatInterval="50000000" /> --> <!-- 默认配置结束 --> </beans> 3.2 添加cas和memcached整合的如下依赖jar包到/CAS/WEB-INF/lib: cas-server-integration-memcached-4.0.0.jar mockito-core-2.1.0-RC.1.jar spymemcached-2.11.2.jar 参考CAS官方配置:https://apereo.github.io/cas/4.2.x/installation/Memcached-Ticket-Registry.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值