1.概念java
CAS:Java (Spring Webflow/Spring Boot) 服務組件,可插拔身份驗證支持(LDAP,Database,X.509,MFA),支持多種協議(CAS, SAML, OAuth, OpenID, OIDC),跨平臺客戶端支持(Java, .Net, PHP, Perl, Apache等),與uPortal,Liferay ,BlueSocket,Moodle, Google Apps等集mysql
SSO:單點登陸簡稱爲 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,用戶只須要登陸一次就能夠訪問全部相互信任的應用系統。域,跨域,Session跨域,Nginx Session共享:分別在session,nginx中已有nginx
2.SSL/TLS/HTTPS之間的關係git
SSL(Secure Sockets Layer 安全套接層),爲Netscape所研發,用以保障在Internet上數據傳輸之安全,SSL通常是https的代名詞,TLS(Transport Layer Security,傳輸層安全)是在SSL3.0的基礎上發展的,繼承了SSL的優勢,都是用以保障在Internet上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程當中不會被截取及竊聽。SSL協議位於TCP/IP協議與各類應用層協議之間,爲數據通信提供安全支持。github
SSL協議可分爲兩層:web
SSL記錄協議(SSL Record Protocol):它創建在可靠的傳輸協議(如TCP)之上,爲高層協議提供數據封裝、壓縮、加密等基本功能的支持。算法
SSL握手協議(SSL Handshake Protocol):它創建在SSL記錄協議之上,用於在實際的數據傳輸開始前,通信雙方進行身份認證、協商加密算法、交換加密密鑰等。spring
3.HTTPS的數據的加密傳輸sql
瀏覽器把協議版本號,支持的加密算法生成的隨機數A發送給服務器,服務器接到客戶端發送過來的加密算法後,查看自身支持的加密算法,肯定雙方後邊使用哪一種加密算法,而後把該算法和數字證書以及生成的隨機數B發給客戶端,客戶端接到服務器發送過來的證數後,獲得證書裏的非對稱加密的公鑰D,而後又生成一個隨機數C,把C和D加密後獲得的一個字符串E發給服務器。服務器接到這個字符串E後,用自身的私鑰解密獲得C,這樣服務器就集齊了 A,B,C,而後利用ABC生成對話加密密鑰 , 由於客戶端也獲得了A,B,C 這樣雙方都能進行加密解密了,至於加密解密的算法就是前面雙方交換加密方法時約定的加密算法。因此能夠看出ABC中,只有C是極難被別人獲得的,這樣保證了安全性,同時這個過程前面用到了非對稱加密,一旦加密密鑰肯定,後面其實用的都是對稱加密了。數據庫
4.使用java的keytool製做證書
keytool -genkeypair -alias serverkey -keypass 111111 -storepass 111111 \ -dname "C=CN,ST=GD,L=SZ,O=vihoo,OU=dev,CN=vihoo.com" \ -keyalg RSA -keysize 2048 -validity 3650 -keystore server.keystore
keytool用法
-rfc" 表示以base64輸出文件,不然以二進制輸出。
-startdate <startdate> 證書有效期開始日期/時間
-alias 實體別名(包括證書私鑰)
-certreq 生成證書請求
-changealias 更改條目的別名
-dname 指定證書擁有者信息 例如: 「CN=名字與姓氏,OU=組織單位名稱,O=組織名稱,L=城市或區域名稱,ST=州或省份名稱,C=單位的兩字母國家代碼」
-destalias <destalias> 目標別名
-ext <value> X.509 擴展
-exportcert 導出證書
-export 將別名指定的證書導出到文件 keytool -export -alias 須要導出的別名 -keystore 指定keystore -file 指定導出的證書位置及證書名稱 -storepass 密碼
-storetype <storetype> 密鑰庫類型
-genkeypair 生成密鑰對
-genseckey 生成密鑰
-genseckey 生成密鑰
-gencert 根據證書請求生成證書
-keystore 指定密鑰庫的名稱(產生的各種信息將不在.keystore文件中)
-keyalg 指定密鑰的算法 (如 RSA DSA(若是不指定默認採用DSA))
-keysize 指定密鑰長度
-keypass 指定別名條目的密碼(私鑰的密碼)
-validity 指定建立的證書有效期多少天
-printcertreq 打印證書請求的內容
-printcrl 打印 CRL 文件的內容
-providername <providername> 提供方名稱
-providerclass <providerclass> 提供方類名
-providerarg <arg> 提供方參數
-providerpath <pathlist> 提供方類路徑
-protected 經過受保護的機制的口令
-importcert 導入證書或證書鏈
-importkeystore 從其餘密鑰庫導入一個或全部條目
-storepass 指定密鑰庫的密碼(獲取keystore信息所需的密碼)
-list 顯示密鑰庫中的證書信息 keytool -list -v -keystore 指定keystore -storepass 密碼
-v 顯示密鑰庫中的證書詳細信息
-file 參數指定導出到文件的文件名
-delete 刪除密鑰庫中某條目 keytool -delete -alias 指定需刪除的別 -keystore 指定keystore -storepass 密碼
-printcert 查看導出的證書信息 keytool -printcert -file yushan.crt
-keypasswd 修改密鑰庫中指定條目口令 keytool -keypasswd -alias 需修改的別名 -keypass 舊密碼 -new 新密碼 -storepass keystore密碼 -keystore sage
-storepasswd 修改keystore口令 keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密碼) -new yushan(新密碼)
-sigalg <sigalg> 簽名算法名稱
-import 將已簽名數字證書導入密鑰庫 keytool -import -alias 指定導入條目的別名 -keystore 指定keystore -file 需導入的證書
5.keytool實例
生成keystore
keytool -genkeypair -alias tomcat -keyalg RSA -validity 3650 -keysize 1024 -keystore H:/ajava/caskey/test.keystore
注意
cas.test.com 必須與以下保持一致
不然會出以下錯誤
導出證書,注意-alias tomcat 與上述的別名須要一致
keytool -keystore H:/ajava/caskey/test.keystore -export -file H:/ajava/caskey/test.cer -alias tomcat -storepass 123456
能夠查看詳情
keytool -list -keystore H:/ajava/caskey/test.keystore -storepass 123456
打印證書
keytool -printcert -file H:/ajava/caskey/test.cer //能夠添加-v
客戶端導入證書(jdk導入證書,不然java不信任會出現錯誤)
keytool -import -keystore F:\JAVA\jdk1.8\jre\lib\security\cacerts -file H:/ajava/caskey/cas.cer -alias tomcat
注意:cacerts這個名字必須是cacerts,由於cacerts是java信任的證書庫(啓動時的jdk),不然會出現以下錯誤,且密碼必須是changeit。不然會出現以下錯誤
生成後綴.p12的證書
keytool -genkeypair -alias mykey -keyalg RSA -storetype PKCS12 -validity 3650 -keysize 1024 -keystore H:/ajava/caskey/mykey.p12
在tomcat中使用(服務端)
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="H:/ajava/caskey/test.keystore" keystorePass="123456" />
這裏沒有采用客戶端認證
備註:
keystoreFile:第一步建立key存放的位置
keystorePass:建立證書時的密碼
truststoreFile:驗證客戶端證書的根證書
truststorePass:建立證書時的密碼
假如客戶端使用了驗證時,須要在瀏覽器導入相應的證書
這裏的例子沒有采用客戶端驗證
6.使用cas實現單點登陸
服務端
下載cas服務器 https://github.com/apereo/cas-overlay-template/tree/5.3
官方文檔 https://github.com/apereo/cas
添加到Idea中,修改pom,添加以下依賴,從新打包
其中比較重要的配置以下
log4j2.xml
配置日誌文件位置(這裏log4j,log4j2,logback 都差很少相似)
<Property name="cas.log.dir" >.</Property> <!-- To see more CAS specific logging, adjust this property to info or debug or run server with -Dcas.log.leve=debug --> <Property name="cas.log.level" >warn</Property>
web-inf下的application.properties文件,假如不肯意更改原配置,那麼能夠在src/resources先新建application.properties,根據springboot的配置文件加載原則,會優先加載src/resources下的application.properties,對密碼啥的是有效的,可是application.yml,application.properties中配置的tomcat相關的配置,打成war包部署在獨立的tomcat上以後, 會失效,緣由是由於spring boot內置的tomcat,也就是說以下配置只對springboot啓動有效,這裏採用的是tomcat(因此以下都註釋了),上面已經配置了,tomcat啓動能夠採用上述介紹的方法(從新打war包)修改配置,也能夠解壓後修改配置,解壓後須要刪除war,不然每次啓動都會先解壓。
#頁面 #server.context-path=/cas #端口 #server.port=8443 #證書的位置 .keystore文件的位置 #server.ssl.key-store=H:/ajava/caskey/test.keystore #指定密鑰庫的密碼 -storepass server.ssl.key-store-password=123456 #別名條目的密碼-keypass #server.ssl.key-password=123456
#用戶名與密碼
#cas.authn.accept.users=casuser::Mellon
開啓服務端,密碼cas.authn.accept.users=casuser::Mellon
不使用ssl(https)那麼須要在application.properties文件中添加,文件位置\WEB-INF\classes\application.properties
#關閉https驗證
cas.tgc.secure=false
CAS 未認證受權服務須要在application.properties文件中添加
#開啓識別json文件,默認false
cas.serviceRegistry.initFromJson=true
在application.properties文件中添加cas.serviceRegistry.initFromJson=true實際是掃描json文件,serviceId表示容許匹配的地址,文件位置WEB-INF\classes\services\HTTPSandIMAPS-10000001.json
{
//該文件能夠是多個,可是該文件名須要知足以下name+id+.json
//加載的類,這裏必須使用這個類
"@class" : "org.apereo.cas.services.RegexRegisteredService",
//能匹配的url,可以匹配多個,也可使用正則,假如須要添加http,那麼編程"serviceId" : "^(https|imaps|http)://.*",,也就是運行經過的域
"serviceId" : "^(https|imaps|http)://.*",
//服務名
"name" : "HTTPS and IMAPS",
//id,惟一標識符
"id" : 10000001,
//描述
"description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
//定義多個服務器的執行順序,數字越大優先級越低
"evaluationOrder" : 10000
}
假如serviceId不能匹配會出現沒有受權的錯誤
客戶端
https://github.com/apereo/java-cas-client 客戶端下載
客戶端配置web.xml
<!--退出過濾器--> <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>https://cas.test.com:8443/cas</param-value> </init-param> </filter> <!--退出監聽器--> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <!--認證過濾器--> <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<!--沒有經過認證重定向的頁面--> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https://cas.test.com:8443/cas/login</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:9002</param-value> </init-param> </filter> <!--驗證過濾器--> <filter> <filter-name>CAS Validation Filter</filter-name> <filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>https://cas.test.com:8443/cas</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:9002</param-value> </init-param> <init-param> <param-name>redirectAfterValidation</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>useSession</param-name> <param-value>true</param-value> </init-param> </filter> <!-- 該過濾器負責實現HttpServletRequest請求的包裹--> <filter> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
測試
7. 配置數據庫密碼認證及md5加密,固然也可使用其餘方式加密。
使用JDBC與MD5
依賴
<!-- 數據庫驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <!--jdbc認證須要添加的,這個是cas的依賴包--> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency>
在application.properties文件中可添加額配置,綠色表示必須
#Query Database Authentication 數據庫查詢校驗用戶名開始
#查詢帳號密碼sql,必須包含密碼字段
cas.authn.jdbc.query[0].sql=select * from sys_user where username=?
#指定上面的sql查詢字段名(必須,密碼)
cas.authn.jdbc.query[0].fieldPassword=password
#指定過時字段,1爲過時,若過時不可用
cas.authn.jdbc.query[0].fieldExpired=expired
#爲不可用字段,1爲不可用,須要修改密碼
cas.authn.jdbc.query[0].fieldDisabled=disabled
#數據庫方言(hibernate的知識)
cas.authn.jdbc.query[0].dialect=
#數據庫驅動
cas.authn.jdbc.query[0].driverClass=
#數據庫鏈接
cas.authn.jdbc.query[0].url=
#數據庫用戶名
cas.authn.jdbc.query[0].user=
#數據庫密碼
cas.authn.jdbc.query[0].password=
#默認加密策略,經過encodingAlgorithm來指定算法,默認NONE不加密
cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
#Query Database Authentication
若密碼無加密,調整passwordEncoder.type=NONE
若密碼加密策略爲SHA,調整passwordEncoder.encodingAlgorithm=SHA
若算法爲自定義,實現org.springframework.security.crypto.password.PasswordEncoder接口,而且把類名配置在passwordEncoder.type
對密碼進行鹽值處理再加密,增長了反查難度,如上面的例子,對密碼只是簡單的加密,不一樣的賬號有可能相同的值,能判斷出密碼是一致,但經過此方案,大大增長了難度,因此安全係數也高了許多,推薦策略
#Encode Database Authentication 開始
#加密次數
cas.authn.jdbc.encode[0].numberOfIterations=2
#該列名的值可替代上面的值,但對密碼加密時必須取該值進行處理
cas.authn.jdbc.encode[0].numberOfIterationsFieldName=
#鹽值固定列
cas.authn.jdbc.encode[0].saltFieldName=username
#靜態鹽值
cas.authn.jdbc.encode[0].staticSalt=.
cas.authn.jdbc.encode[0].sql=select * from sys_user_encode where username=?
#對處理鹽值後的算法
cas.authn.jdbc.encode[0].algorithmName=MD5
cas.authn.jdbc.encode[0].passwordFieldName=password
cas.authn.jdbc.encode[0].expiredFieldName=expired
cas.authn.jdbc.encode[0].disabledFieldName=disabled
cas.authn.jdbc.encode[0].url=
cas.authn.jdbc.encode[0].dialect=
cas.authn.jdbc.encode[0].user=sa
cas.authn.jdbc.encode[0].password=
cas.authn.jdbc.encode[0].driverClass=
#Encode Database Authentication 結束
8. 退出
#容許發出退出控制退出後轉發url cas.logout.followServiceRedirects=true
退出後跳轉到指定頁面,假如只有https://ip/cas/logout,那麼會跳到註銷頁面
<a href ="https://ip/cas/logout?service=https://demo.testcas.com/cas-server/login" />
以下配置(不須要配置)
cas.logout.redirectParameter=service#上面a href的service的由來cas.logout.confirmLogout=false #是否須要出現confirm窗口cas.logout.removeDescendantTickets=false #是否須要移除Ticket