一、关于SSO单点登录

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

二、CAS基本原理

    

nginx crt能用吗_nginx crt能用吗

 

  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等就可以了

nginx crt能用吗_重定向_02

四、https配置(Tomcat、Nginx)

tomcat直接支持https,参考

#生成证书,密码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 crt能用吗_重定向_03

企业中一般配置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

nginx crt能用吗_重定向_04

五、整合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登录

nginx crt能用吗_nginx crt能用吗_05