CAS (5) —— Nginx代理模式下浏览器访问CAS服务器配置详解
tomcat版本: tomcat-8.0.29
jdk版本: jdk1.8.0_65
nginx版本: nginx-1.9.8
cas版本: cas4.1.2
cas-client-3.4.1
参考来源:
jasig.github.io:CAS protocol
https://github.com/Jasig/java-cas-client
通过Proxy访问其它Cas应用
CAS负载均衡配置——SSL篇
CAS负载均衡配置
CAS客户端集群
以下的示例采用我博客的另外两篇文章中搭建好的测试环境举例
CAS (1) —— Mac下配置CAS到Tomcat(服务端)
CAS (2) —— Mac下配置CAS到Tomcat(客户端)
CAS (3) —— Mac下配置CAS客户端经代理访问Tomcat CAS
Mac为nginx安装nginx-sticky-module
【高可用HA】Nginx (1) —— Mac下配置Nginx Http负载均衡(Load Balancer)之101实例
Nginx (2) —— Mac下配置Apache Httpd的Https/SSL (待出)
目标架构
此代理非彼代理
在CAS官方网站上给出了一个“Proxy Web Flow Diagram”:
顺序图:(来源于http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html)
这个方案主要适用一种场景:
有两个应用App1和App2,它们都是受Cas Server保护的,即请求它们时都需要通过Cas Server的认证。现需要在App1中通过Http请求访问App2,显然该请求将会被App2配置的Cas的AuthenticationFilter拦截并转向Cas Server,Cas Server将引导用户进行登录认证,这样我们也就不能真正的访问到App2了。针对这种应用场景,Cas也提供了对应的支持。通过Proxy访问其它Cas应用
无论是用中文关键字在“度娘”,还是用英文关键字再“谷哥”上搜索,多数文章都是描述上面这样一个场景。
而我这里介绍的“代理”,并非是上述场景——依靠代理去验证ticket,“代理”在此的角色是:
- 只做分发反向代理(未来的负载均衡器)
* 注意:所以说“此代理非彼代理”
准备
要搭建上面这个环境会相对复杂,我们需要参照之前的文章准备以下必备的组件或环境:
2个Tomcat服务器作为客户端应用程序服务器(即cas的客户端)
app1.hoau.com:8081/8413(http/https) app2.hoau.com:8082/8423(http/https)
参照Tomcat Cluster、Tomcat SSL和CAS Client
1个配置好SSL的Nginx服务器作为中间层代理转发服务器(后可扩展为LoadBalancer)
proxy.sso.hoau.com:85/443(http/https)
参照Nginx Load Balancer与Nginx Sticky Session
另一个1个带有SSL的Tomcat服务器作为CAS服务器
sso.hoau.com:8083/8433(http/https)
参照Tomcat SSL与CAS Server
关键配置
代理服务器(Nginx x 1)
nginx.confhttp
server:
server { listen 85; server_name proxy.sso.hoau.com; location / { #index index.html index.htm; #设置主机头和客户端真实地址,以便服务器获取客户端真实IP proxy_set_header Host $host; proxy_set_header Referer $http_referer; proxy_set_header Cookie $http_cookie; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; #禁用缓存 #proxy_buffering off; proxy_connect_timeout 3; proxy_send_timeout 30; proxy_read_timeout 30; proxy_pass http://cas_server_http; }
upstream:
upstream cas_server_http { #根据ip计算将请求分配各那个后端tomcat,许多人误认为可以解决session问题,其实并不能。 #同一机器在多网情况下,路由切换,ip可能不同 #ip_hash; #sticky; #Richard: http server localhost:8083 weight=1 srun_id=c; #server localhost:8084 weight=1 srun_id=c; jvm_route $cookie_JSESSIONID|sessionid reverse; }
*注意:
(1)以上的“jvm_route $cookie_JSESSIONID|sessionid reverse;”是关键配置,因为CAS是依赖于Session和Cookie进行身份验证的。
(2)srun_id=c,其中“c”需要与CAS服务器Tomcat server.xml文件里的jvmRoute配置“
” https
server:
server { listen 443; server_name proxy.sso.hoau.com; ssl on; ssl_certificate /Users/Richard/Documents/Dev/servers/cluster/nginx/keys/server.crt; ssl_certificate_key /Users/Richard/Documents/Dev/servers/cluster/nginx/keys/server.key; ssl_session_timeout 5m; ssl_protocols SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header Referer $http_referer; proxy_set_header Cookie $http_cookie; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-FORWARDED-HOST $server_addr; proxy_set_header X-FORWARDED-PORT $server_port; proxy_connect_timeout 3; proxy_send_timeout 30; proxy_read_timeout 30; proxy_pass https://cas_server_ssl; } }
*注意:以上的ssl为关键配置“ssl_certificate”和“ssl_certificate_key”需要指向正确的证书和密钥。
upstream:
upstream cas_server_ssl { #Richard: https todo server sso.hoau.com:8433 weight=1 srun_id=c; #server sso.hoau.com:8443 weight=1 srun_id=c; jvm_route $cookie_JSESSIONID|sessionid reverse; }
*注意:以上http和https可以只配一项,或两者兼存皆可,端口不要冲突。
CAS客户端应用服务器(Tomcat x 2)
以下客户端的蓝本可以在github上收到(关键字:“cas-sample-java-webapp”),我这里只贴出自己的关键点和修改后的结果。
CAS客户端的应用服务器有两台,如果不使用Spring Security的集成,比较关键配置就只有pom.xml(编译)和web.xml(部署):
两个环境编译类似,pom.xml(贴全了,有无冗余请自行解决):
*注意:以下Spring Security相关依赖为非必须
4.0.0 iamlabs.unicon.net cas-sample-java-webapp 0.0.1-SNAPSHOT war CAS Example Java Web App A sample web application that exercises the CAS protocol features via the Java CAS Client. cas-sample-java-webapp org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.7 3.2.4.RELEASE 3.4.1 commons-logging commons-logging 1.1.1 org.slf4j slf4j-api 1.7.13 org.slf4j slf4j-simple 1.7.13 org.slf4j slf4j-log4j12 1.7.13 org.opensaml opensaml1 1.1 javax.servlet javax.servlet-api 3.1.0 provided org.jasig.cas.client cas-client-core ${casclient.version} javax.servlet servlet-api org.jasig.cas.client cas-client-integration-tomcat-common ${casclient.version} commons-codec commons-codec 1.6 org.apache.santuario xmlsec 1.4.3 org.springframework spring-core ${spring.version} org.springframework spring-beans ${spring.version} org.springframework spring-context ${spring.version} org.springframework spring-web ${spring.version} org.springframework.security spring-security-core ${spring.version} org.springframework.security spring-security-web ${spring.version} org.springframework.security spring-security-config ${spring.version} https://app1.hoau.com:8413
web.xml:
log4jConfigLocation /WEB-INF/log4j.properties org.springframework.web.util.Log4jConfigListener CAS Validation Filter org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter casServerUrlPrefix https://proxy.sso.hoau.com:443/cas serverName https://app1.hoau.com:8413 redirectAfterValidation true useSession true acceptAnyProxy true CAS Authentication Filter org.jasig.cas.client.authentication.AuthenticationFilter casServerLoginUrl https://proxy.sso.hoau.com:443/cas/login serverName https://app1.hoau.com:8413 CAS HttpServletRequest Wrapper Filter org.jasig.cas.client.util.HttpServletRequestWrapperFilter CAS Validation Filter /* CAS Authentication Filter /* CAS HttpServletRequest Wrapper Filter /* index.jsp *注意:
- “CAS Validation Filter”需要放在“CAS Authentication Filter”之前
此代理非彼代理
网上一些文章说的需要配置诸如:- “SingleSignOutHttpSessionListener”
- “SingleSignOutFilter”
- “ticketValidatorClass”
- “ProxyValidate”
- “ProxyTicketReceptor”
均不需要
如果误配了SingleSignOutFilter,会出现异常
Caused by: java.io.IOException: Server returned HTTP response code: 500 for URL: https://proxy.sso.hoau.com:443/cas/proxyValidate?ticket=ST-31-TM9EbFoQbasNdXh11HaJ-cas01.sso.hoau.com&service=https%3A%2F%2Fapp2.hoau.com%3A8423%2Fcas2%3Bjsessionid%3D0CEB865B53E64FF31BF02A496DF73860.tomcat2
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:429) ... 24 more
如果为了在https下录制自动化测试脚本,会修改classpath下/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security的java.security文件,那么也可能出现类似的错误。
https://app2.hoau.com:8423
web.xml配置同上
*注意:修改端口
CAS服务器(Tomcat x 1)
服务端https://sso.hoau.com:8433
*注意:
系列文章CAS (1) —— Mac下配置CAS到Tomcat(服务端)中介绍服务端配置也无需任何修改。
以下配置:
- “Proxy (PGT acquisition)”
- “Modern proxy-service validation”
均不需要
测试
*1. 访问“https://app1.hoau.com:8413/cas1”
会重定向到“https://proxy.sso.hoau.com/cas/login?service=https%3A%2F%2Fapp1.hoau.com%3A8413%2Fcas1”
*2. 然后输入用户明密码(test01/psw01)
如果验证成功,则会将浏览器重定向到app1的登陆成功页面。
*3. 再次访问“https://app1.hoau.com:8413/cas1”
可以直接进入登陆成功页,而无需输入用户名密码。
*4. 访问另一应用
同样可以通过test01用户直接进入登陆成功页,而无需输入用户名密码。
代理下的网络顺序分析
参照另一文章:(待出)
源代码
还在准备,如果需要的童鞋请留言。