分布式系统统一登录的实现
一、 運用Redis緩存將Token存入緩存;
將 session 全部存放到 Redis 中,Redis 全局管理數據,因為獨特的 key 過期時間特性,對應 session 的過期特性,也很般配。另外,Redis 比較輕量,性能也很好。
用戶在登錄的時候如果通過鑒權體系的鑒定,可以生成 Token 數據,以 Token 作為鍵名,用戶登錄信息作為值,寫入到 Redis 中,設置過期時間,并將 Token 寫入 cookie 中。用戶下次進行敏感操作的時候,通過攔截器判斷用戶請求頭中 cookie 的 token 字段是否能在 Redis 中查詢到數據。如果能查詢到,就允許用戶進行操作并刷新登錄有效期,否則就返回登錄 URL,這樣一個分布式系統的單點登錄系統就實現了
二、配置負載均衡策略時使用源地址哈希法。相同的IP客戶端,如果服務器列表不變,將映射到同一個后臺服務器進行訪問
一致性哈希算法與C++實現
三、Spring Security的session共享
1.構建一個SpringSecurity應用
1.1Spring Boot 版本是 2.0.4.RELEASE,引入security啟動器
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>1.2 整體部分包括認證和授權,即你是誰,你有哪些權限
- authentication 的思路是用戶傳過來的表單數據,username和password 在spring security 由Authentication 封裝, 從 SecurityContextHolder 中獲取 SecurityContext 再獲取 Authentication,即可獲取到用戶提供的認證消息
而UserDetail是數據庫測的用戶信息,保存著密碼和其它更詳細的用戶信息,實現UserDetailsService 的方法即根據
用戶名從數據庫中獲取UserDetail,這就是大致的認證過程,如果認證失敗,拋出相應的異常,如果認證成功進行鑒權。
- authorization思路授權過程是,獲取當前請求的url,從數據庫中根據此url查詢出訪問此url的角色有哪些 ,然后將用戶
當前的角色和請求該路徑應當具有的角色進行比較,如果用戶的角色在其中,則鑒權通過,否則拋出異常 。
1.3 Spring Security是如何實現的。在servlet的環境中是使用Filter實現的
在引入Spring Security 依賴的時候就會在META-INF/spring.factory 實例化SecurityFilterAutoConfiguration ,將DelegatingFilterProxy 過濾器 以 “springSecurityFilterChain“的beanName注冊到“/”到servlet容器中,DelegatingFilterProxy
本身什么也不做,包含FilterChainProxy對象,而FilterChainProxy對象里有 private List filterChains ,
真正干活的是SecurityFilterChain 實例,SecurityFilterChain 中 有List getFilters() 方法,真正過濾的是這里的Filter
這里大致有SecurityContextPersistenceFilter、HeaderWriterFilter、LogoutFilter、UsernamePasswordAuthenticationFilter等filter ,這種代理的方式注入filter,使Filter不至于十分冗長和復雜
1.4 數據庫大致介紹
用戶表 :用戶名,頭像,中文名,加密過的密碼
角色表:角色名,角色中文名名 角色名以“ROLE_”開頭,例如ROLE_admin
用戶角色中間表:雙方的id
菜單表 :正則形式的url ,其它數據,自關聯也可以
角色菜單中間表:雙發的id
如果沒有配置角色,即登入就可以訪問了
1.5 具體使用流程
提供賬號和密碼,密碼或賬號不對時不能登入
登入用戶后,訪問對應的資源url,沒有權限時不能訪問,即做到了權限控制,而且這種權限控制是基于數據可配置,十分靈活
1.6 使用的注意事項 登入成功后,還能記住用戶信息 ,使用的是 cookie 和session ,但nginx部署springBoot集群時,會導致
輪詢訪問所得到的session不同,
nginx核心配置
#測試security中的session機制;upstream delegating_server{server 127.0.0.1:8082 weight=20;server 127.0.0.1:8083 weight=5;}server {listen 80;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location /cache {proxy_pass http://cache_server/;root html;index index.html index.htm;}location /security {#做負載均衡時,其中一個節點掛掉,默認是1分鐘后轉發給其它的節點proxy_connect_timeout可以更改時長proxy_pass http://delegating_server;root html;index index.html index.htm;proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 3; proxy_read_timeout 1; proxy_send_timeout 1; }當停掉一個springBoot實例后,就可以恢復正常,
2.使用redis實現session共享
引入依賴
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>redis配置 一下,此處注意一下,spring 默認使用lettuce 連接redis服務
總結
以上是生活随笔為你收集整理的分布式系统统一登录的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring学习(6):使用xml方式实
- 下一篇: spring mvc学习(13)wind