elasticsearch+Nginx+django+cas+mysql平臺搭建實現單點登錄認證
系統結構功能圖:
系統簡介:
1.django項目放到了nginx容器中,採用的是nginx+uwsgi的方案。django訪問端口5050。
nginx listen 8000端口,訪問8000端口會轉到5050 端口
2.nginx反向代理elasticsearch,elasticsearch的訪問端口爲9200,採用nginx反向代理之後,當django中需要從elasticsearch中查詢數據的時候只需要訪問nginx的8081端口,爲了保護elasticsearch的安全性在nginx中設置了訪問規則。
3.cas服務器部署到tomcat中,cas的用戶名密碼存儲在mysql數據庫中。
對於用戶而言只可以通過8000端口訪問整個系統(投入使用之後只需要將8000改爲80即可,其他地方都不用做更改)
詳細內容請看下面在搭建系統過程中的介紹。
cas服務器搭建:
一、創建祕鑰
1.新建存放key的目錄mkdir -p/usr/local/keys
2.利用jdk自帶的keytool生成祕鑰庫:
keytool -genkey -alias tomcat -keypasschangeit -keyalg RSA -keystore /usr/local/keys/server.keystore
注:tomcat爲別名 server .keystore 爲生成的祕鑰文件 changeit 爲密碼,爲了方便所有的密碼都設置爲changeit,在生成祕鑰庫的時候第一項寫訪問的域名例如www.jiuge.lol其餘的隨便寫
3.導出證書:
keytool -export -alias tomcat -keypass changeit -file/usr/local/keys/server.crt -keystore/usr/local/keys/tomcat.keystore
導出的時候輸入之前的密碼:changeit
4.將數字證書導入jre中
在導入之前可以把已有的證書刪除:
keytool -delete -alias tomcat(隨便起的別名) -keystore
/usr/local/jdk1.8/jre/lib/security/cacerts -storepass changeit
然後在進行導入操作:
keytool -import -alias tomcat -file/usr/local/keys/server.crt -keypass changeit -keystore /usr/local/jdk1.8/jre/lib/security/cacerts
注:這裏的jre地址一定要和tomcat使用的jre地址一致。
輸入密碼(注:這裏的輸入的密碼不是上面設置的密碼是固定的密碼changeit,爲了不弄混,在之前設置的密碼和這個設置相同就可以了)
5.查看證書是否導入成功:
keytool -list -keystore /usr/local/jdk1.8/jre/lib/security/cacerts
輸入changeit密碼可以看到證書成功導入了
二、配置https
修改tomcat中的server.xml,添加如下內容
此時開啓tomcat訪問:
說明https配置生效:
三、搭建cas服務器以及客戶端測試
1.部署cas
下載cas(網址:http://www.jasig.org/cas)
解壓之後在models文件夾下面有一個cas-server-webapp-3.5.0.war,將其改名爲cas.war 放到webapps目錄下作爲單點登錄服務器:
此時訪問
輸入用戶名密碼(相同字符串就行)注:4.0版本以上cas的默認帳號密碼爲casuser/Mellon
出現此界面則說明cas服務器搭建成功
2、對cas客戶端進行部署測試
下載cas-client-core-3.2.1.jar,commons-logging-1.1.jar並將其拷貝到測試目錄examples中的lib下面
此時若在同一臺機器上做測試可以安裝兩個tomcat,其中tomcat-app作爲客戶端
對於一臺機器安裝兩個tomcat的方法是:
修改環境變量/etc/profile
然後source立即生效
然後在修改tomcat啓動文件catalina.sh
將所有的CATALINA_HOME更改爲CATALINA_HOME2
(%s/CATALINA_HOME/CATALINA_HOME2/g)
最後只修改server.xml將那些端口改爲沒有佔用的即可(這裏修改成7070)
接下來就要進行客戶端的配置:
這裏用的是tomcat自帶的examples目錄做測試
修改其web.xml:
添加:
<!--======================== 單點登錄開始 ======================== -->
<!-- 用於單點退出,該過濾器用於實現單點登出功能,可選配置-->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://www.jiuge.lol:9443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://www.jiuge.lol:7070</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->
<filter>
<filter-name>CAS ValidationFilter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://www.jiuge.lol:9443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://www.jiuge.lol:7070</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS ValidationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
該過濾器負責實現HttpServletRequest請求的包裹,
比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登錄用戶的登錄名,可選配置。
-->
<filter>
<filter-name>CASHttpServletRequest Wrapper Filter</filter-name>
<filter-class>
org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CASHttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。
比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<filter>
<filter-name>CAS Assertion ThreadLocal Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion ThreadLocal Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--======================== 單點登錄結束 ======================== -->
此時客戶端配置完成可以訪問測試:
輸入http:/jiuge.lol:7070/examples/servlets/servlet/HelloWorldExample
會跳轉到如下認證界面
輸入用戶名密碼(jiuge)
注意:此處的結果雖然和不做認證顯示相同,但是仔細觀察就會發現在地址欄會有票據信息顯示的
若要把客戶端tomcat放在其他機器只需要導入cas服務器的證書到jre中即可(server.crt);其他的配置和上面的完全一樣。
tomcat的CLOSEWAIT
解決方法:
1.(暫時生效,重新啓動 linux 後,會還原成預設值)
sysctl -w net.ipv4.tcp_fin_timeout=30
sysctl -w net.ipv4.tcp_keepalive_time=1800
sysctl -w net.ipv4.tcp_keepalive_probes=2
sysctl -w net.ipv4.tcp_keepalive_intvl=2
2.(永久生效)
vi /etc/sysctl.conf
# Decrease the time default value fortcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 30
# Decrease the time default value fortcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1800
# 探測次數
net.ipv4.tcp_keepalive_probes=2
# 探測間隔秒數
net.ipv4.tcp_keepalive_intvl=2
編輯完 /etc/sysctl.conf,要重啓network 纔會生效
[root@temp /]# /etc/rc.d/init.d/networkrestart
**********************************************************************************
PS: 發生CLOSE_WAIT 的原因,可能在於程式內 一端的Socket使用close後,另一端的Socket沒有使用close.檢查一下代碼內是否有Server端在某些異常情況時,沒有關閉Socket,將之修改,應可改正此一問題
Django Nginx+uwsgi 安裝配置
安裝django
pip install django
然後新建一個項目lcsite (django-admin.py startproject lcsite)
再新建一個app lc(python manage.py startapp lc)
安裝nginx:詳細見linux7學習筆記.doc
安裝uwsgi
pip install uwsgi
對於啓動方式常見的有xml 和ini方式這裏選擇 ini的方式
利用ini的方式配置uwsgi 在/etc/目錄下新建 uwsgi5050.ini 文件添加如下配置
配置nginx的conf文件在server中添加如下配置:
server {
listen 8000;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5050; //必須和uwsgi中的設置一致
uwsgi_param UWSGI_SCRIPT lcsite.wsgi; //入口文件,即wsgi.py相對於項目根目錄的位置,“.”相當於一層目錄
uwsgi_param UWSGI_CHDIR /website/lcsite; //項目根目錄
index index.html index.htm;
client_max_body_size 35m;
}
}
啓動nginx: nginx
啓動uwsgi: uwsgi --ini /etc/uwsgi5050.ini(注意:要用普通賬號啓動,否則日誌裏面會有警告信息)
若出現 如下錯誤:
則應該在uwsgi.py(存放在lcsite文件下)中添加如下配置:
訪問nginx服務器(用的是8000端口):
正常運行,配置結束
django_cas_ng的搭建
安裝 django-cas-ng
接下來修改django的配置文件:
首先修改setting文件:
說明:
CAS_SERVER_URL爲cas服務器的地址(注意對應好端口,前面搭建cas服務器用的9433端口,這裏爲了方便記憶修改了cas服務器的端口爲8433)
CAS_REDIRECT_URL= '/lc' 指定cas認證完成之後重定向地址 默認”/”
修改url.py文件:
這裏的url匹配規則是測試用的,如果是在實際項目中,可以研究一個完善的url,以及自定義錯誤頁面,避免url被暴露。
這裏在views中簡單做了一下過濾,認證通過轉到index.html 沒有認證轉到認證界面login這裏採用的是login_required模塊
這裏可以運行一下以下兩條命令查看一下
接下來就用到前面配置cas服務器生成的server.crt證書了
因爲django是python的框架。所以查看Python的證書
需要把server.crt證書的內容複製到這個目錄下的cacert.pem中
這裏的證書都是pem擴展名的,然而cas服務器的證書是crt擴展名的,crt擴展名的證書是屬於DER編碼格式的是一種二進制編碼的無法查看,所以要把它轉換爲擴展名爲.pem
ASCII(Base64)編碼,可以閱讀的格式。
具體的轉換方法:
1. 用IE瀏覽器間接轉換,先把crt格式證書導入IE瀏覽器,再導出來,這時候成了cer格式證書,再用命令把cer格式證書轉換pem格式證書
2. opensslx509 -inform der -in server.cer -out server.pem
可以查看其內容如下
最後將這部分內容複製到python目錄下的cacert.pem之中,完成所有的配置。
接下里進行測試:
運行: uwsgi --ini /etc/uwsgi5050.ini
查看運行日誌:
正常啓動,訪問瀏覽器
輸入www.jiuge.lol訪問網站主目錄:
跳轉到cas服務器認證login界面
->輸入用戶名密碼跳轉回主頁面
自定義錯誤頁面
註銷認證:
cas-mysql認證:
由於之前的cas認證中只是輸入相同的用戶名和密碼就可以認證通過,這顯然和符合實際應用,要把可以訪問的用戶名、密碼存儲在mysql數據中,每次認證的用戶名要去mysql數據庫中進行查詢。
這裏爲了更好的對應mysql的版本選擇了cas4.2.7版本,另一方面這個版本需要的jar包相對比較少。
1.安裝並配置mysql數據庫:
yum install mysql
yum install mysql-devel
wgethttp://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
rpm -ivhmysql-community-release-el7-5.noarch.rpm
yum install mysql-community-server
更改mysql root用密碼
修改默認編碼:
遠程連接設置:
mysql> grant all privileges on *.* to root@'%'identifiedby 'password';
配置好mysql數據庫之後可以創建一個cas_user用戶表,然後插入一條數據:
CREATE TABLE `cas_user` (
`id` bigint(16) NOT NULL ,
`account` varchar(30) DEFAULT NULL ,
`password` varchar(255) DEFAULT NULL ,
`valid` tinyint(1) DEFAULT NULL ,
PRIMARY KEY(`id`)
) ENGINE=InnoDB ;
insert into`cas_user`(`id`,`account`,`password`,`valid`) values(2017193618796666,'test',MD5('test001'),1);
2.只需要重新部署cas.war到webapps中即可
首先現在cas4.2.7版本在github上面找到對應的zip包即可。
這裏要注意一定解壓之後會發現這個和之前的cas3.5有一點不同,之前的在models中就有cas.war包,這個版本中沒有這個包。
所以要生成cas.war
首先安裝一個構建項目工具-Gradle:
wget https://downloads.gradle.org/distributions/gradle-3.2.1-all.zip
unzip gradle-3.2.1-all.zip
放到/usr/local
配置環境變量:
GRADLE_HOME=/usr/software/gradle-3.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}
檢測:
gradle -version
安裝成功
接下里構建項目
解壓cas4.2.7--cd cas4.2.7-cd cas-server-webapp
然後執行 gradle build (時間會有點長)
然後查看該目錄文件會多了一個build文件夾
然後進入libs文件夾查看:
這個已經生成了我們想要的war包
接下來只需要將war包複製到tomcat/webapps下並改名爲cas.war即可
下面就要生成所需要的兩個jar包:
cas-server-support-jdbc-4.2.7.jar
和mysql-connector-Java-5.1.5.bin.jar
#cdcas-4.2.7/cas-server-support-jdbc
#gradle build(等候一段時間)
可以看到生成了build文件夾在build/libs/下面可以看到:
將這個jar包複製到cas項目下的 WEB-INF/lib下面
對於mysql-connector-Java-5.1.5.bin.jar只需要在百度上下載即可,同樣也放到上面的目錄下
3.配置cas讀數據庫驗證用戶並對密碼進行加密
打開deployerConfigContext.xml
搜索這條配置並註釋之
<!-- <aliasname="acceptUsersAuthenticationHandler"alias="primaryAuthenticationHandler" />-->
而後添加如下配置:
注:上面三個綠色框由上到下一次對應你的數據庫名稱,mysql登錄用戶名,mysq登錄密碼。
打開cas.properties
只需要添加如下代碼即可
注:對應好自己的表名稱以及字段名稱
把web容器以及相應的容器重啓一下
此時通過我的django客戶端訪問es服務器會出現如下錯誤:
解決的方法是:
只需要修改HTTPSandIMAPS-10000001.json
此時對以上所做的進行一個簡單的測試:
django放到了nginx容器中,所以對外只暴露了nginx的端口
訪問nginx(django端口爲5050),相當於訪問django首頁。
跳轉到登錄界面(進行認證)
輸入用戶名密碼:(隨便輸入或者輸入cas4.0+版本的默認帳號密碼(casuser/Mellon))
輸入mysql中的用戶名密碼:
可以發現正常訪問了django的首頁,所以也證明整個配置沒有問題
因爲elasticsearch和其他的認證模塊在配置上沒有關聯,所以在最後進行配置,
對於代理elasticsearch只需更改nginx的配置文件即可:
如果想給elasticsearch配置一個管理員用戶可以進行如下配置:
1.首先在nginx目錄下新建一個存放祕鑰的文件夾http_passwd_user(名字任意)
2.修改nginx的配置文件nginx.conf
添加如下內容
3.用openssl生成認認證文件:
printf "admin:$(openssl passwd -cryptadmin007)\n" > /usr/local/nginx/http_passwd_user/admins
如果無法正常訪問es則需要在iptables配置文件中加上紅色部分的規則
在公司的服務器django-cas-ng採用的是源碼安裝,而不是pip安裝,源碼安裝是不會安裝certifi這個包,所以要單獨安裝:
將這個包解壓安裝
然後把cas服務器上的證書放到了自己的本地服務器的這裏面(複製進去就可以,如果不是base64編碼的可以先轉換一下)