這段時間斷斷續續學習了單點登陸的相關知識,這裏彙總一下,加深下記憶。java
單點登陸(Single Sign On,簡稱SSO) 是當前比較流行的一種用於企業業務整合的解決方案。mysql
SSO並不具體指哪種框架,而是一種思想。企業裏,若是想讓用戶只登陸一次,就能夠訪問全部互相信任的應用系統時,咱們就能夠採用SSO。git
例如阿里下有淘寶網、天貓網、聚划算等網站。當咱們在其中一個網站登陸了,在同個瀏覽器訪問其餘的幾個網站時,就無需再進行登陸。github
如下根據我本身的理解畫的兩個時序圖,來簡單介紹下單點登陸中,用戶登陸認證流程和用戶註銷流程。web
用戶登陸認證流程:算法
用戶註銷流程:spring
CAS(Cantral Authentication Service)是耶魯大學發起的一個開源項目(github地址爲https://github.com/apereo/cas),是單點登陸的實現方式之一。sql
CAS分爲CAS服務端和CAS客戶端。數據庫
CAS服務端負責完成對用戶的認證工做,CAS服務端須要獨立部署。apache
CAS客戶端集成到每一個應用系統上。當用戶須要在認證以後才能訪問應用系統受保護資源時,應用系統判斷該用戶是否已認證,若是沒有認證,則重定向到CAS服務端進行身份認證。
CAS協議能適配大多數語言編寫的應用系統,所以應用十分普遍。
如下演示搭建CAS,基礎環境爲:JDK1.八、tomcat8.五、apache-maven-3.6.1。
因爲是在本地搭建,所以我在hosts文件,添加如下三個域名,解析到172.0.0.1。方便後續區分是客戶端仍是服務端。
127.0.0.1 cas.server.com 127.0.0.1 cas.client.a.com 127.0.0.1 cas.client.b.com
一、從github上下載cas-overlay-template(地址:https://github.com/apereo/cas-overlay-template/tree/5.3),此處使用5.3版本。
二、使用maven命令打包(須要在本地安裝Maven)。Windows下爲.\build.cmd package
,Linux下爲./build.sh package
。打包後的war包在target目錄下。
三、因爲cas-server-webapp-tomcat-5.3.14.war很大,下載比較慢。能夠直接到 http://oss.sonatype.org/
找到對應版本的war包。下載後放到本地Maven倉庫的對應位置便可。
四、因爲CAS默認使用的是基於https協議。部署CAS服務端時,須要添加證書,或者改成兼容使用http協議。這裏爲了方便,直接修改war包的配置文件,兼容使用http協議。
4.1 在cas.war部署包下找到\WEB-INF\classes\application.properties
添加:
cas.tgc.secure=false cas.serviceRegistry.initFromJson=true
4.2 在cas.war部署包下找到\WEB-INF\classes\services\HTTPSandIMAPS-10000001.json
,修改 serviceId 的值,添加http:
"serviceId" : "^(https|http|imaps)://.*",
五、在cas.war部署包下找到\WEB-INF\classes\application.properties
,將server.port修改成8080。
六、將修改後的cas.war包放到tomcat的webapps目錄下,啓動tomcat,在瀏覽器中輸入http://localhost:8080/cas
,默認用戶名:casuser
,默認密碼:Mellon
。若是要修改密碼,能夠修改\WEB-INF\classes\application.properties
文件。
cas服務登陸界面以下圖:
上面是經過寫在配置文件中的用戶名和密碼進行登陸的,咱們能夠修改成從數據庫中獲取。
一、修改CAS項目的pox.xml,添加如下依賴。
<dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc-drivers</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency>
二、根據搭建CAS服務端
章節,從新打包部署包。
三、修改在cas.war部署包下的\WEB-INF\classes\application.properties
文件。
3.1 註釋掉默認的用戶# cas.authn.accept.users=casuser::Mellon
。
3.2 添加如下內容,具體配置含義,能夠到官方文檔查看。
cas.authn.jdbc.query[0].url=jdbc:mysql://{mysql.IP}:3306/{db.name}?useUnicode=true&characterEncoding=utf-8 cas.authn.jdbc.query[0].user={username} cas.authn.jdbc.query[0].password={password} # 指定查詢帳號密碼sql cas.authn.jdbc.query[0].sql=select * from user where username=? # 指定密碼字段 cas.authn.jdbc.query[0].fieldPassword=password # 數據庫驅動 cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver #密碼加密策略,若是密碼字段沒有加密,則這一段配置能夠省略 # 默認加密策略 cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8 # 指定密碼字段加密算法爲MD5 cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
四、修改war包後,根據搭建CAS服務端
章節,從新部署。輸入數據庫中的帳號和密碼,便可成功登陸。
本部分參考SpringBoot整合CAS單點登陸 搭建。
搭建的客戶端代碼,存放在個人github倉庫。
一、使用springboot,搭建web項目,項目名叫cas-client-A
,而且引入如下依賴。
<dependency> <groupId>net.unicon.cas</groupId> <artifactId>cas-client-autoconfig-support</artifactId> <version>1.4.0-GA</version> </dependency>
二、在啓動類添加註解@EnableCasClient
。
三、在配置文件,添加如下配置。
cas.server-url-prefix=http://cas.server.com:8080/cas cas.client-host-url=http://cas.client.a.com:9001 server.port=9001 # 填CAS服務器的登陸地址 cas.server-login-url=http://cas.server.com:8080/cas/login #自定義的退出url,退出成功後跳轉路徑 casClientLogoutUrl=http://cas.server.com:8080/cas/logout
四、添加過濾器,用於從請求中獲取用戶CAS登陸信息,生成本地用戶登陸信息。
public class LocalUserInfoFilter implements Filter { @Override public void init(FilterConfig filterConfig) { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest request_ = (HttpServletRequest) request; String loginName = getAccountNameFromCas(request_); if (!StringUtils.isEmpty(loginName)) { request_.getSession().setAttribute("loginName", loginName); } chain.doFilter(request, response); } @Override public void destroy() { } /** * 從cas中獲取用戶名 * * @param request * @return */ private static String getAccountNameFromCas(HttpServletRequest request) { Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); if (assertion != null) { AttributePrincipal principal = assertion.getPrincipal(); return principal.getName(); } else return null; } }
五、添加cas配置類。
@Configuration public class FilterConfig { @Value("${cas.server-url-prefix}") private String CAS_URL; @Value("${cas.client-host-url}") private String APP_URL; /** * 單點登陸退出 */ @Bean public FilterRegistrationBean singleSignOutFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new SingleSignOutFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.addInitParameter("casServerUrlPrefix", CAS_URL); registrationBean.setName("CAS Single Sign Out Filter"); registrationBean.setOrder(1); return registrationBean; } /** * 從request中獲取cas登陸信息,根據登陸信息獲取當前用戶,建立本地session */ @Bean public FilterRegistrationBean registrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new LocalUserInfoFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.setName("localUserInfoFilter"); registrationBean.setOrder(2); return registrationBean; } }
六、添加controller。當用戶登陸後,訪問/
,返回當前系統的端口號。當用戶訪問/logout
,調用cas服務端註銷URL,註銷登陸。
@RestController public class TestController { @Value("${server.port}") private String serverPort; @Value("${casClientLogoutUrl}") private String clientLogoutUrl; @GetMapping("/") public String hello() { return "我是VIP:" + serverPort; } @GetMapping("/logout") public void logout(HttpSession session, HttpServletResponse response)throws Exception { session.invalidate();//銷燬session //使用cas退出成功後,跳轉頁面 response.sendRedirect(clientLogoutUrl); } }
七、根據步驟1-7,建立cas-client-B項目,項目配置文件的 cas.client-host-url
和 server.port
修改成下面兩個值。
cas.client-host-url=http://cas.client.b.com:9002 server.port=9002