日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

告別繁瑣操作,實現一次登錄產品互通

來源: 責編: 時間:2024-09-10 09:50:55 133觀看
導讀最近開發新產品,然后老板說我們現在系統太多了,每次切換系統登錄太麻煩了,能不能做個優化,同一賬號互通掉。作為一個資深架構獅,老板的要求肯定要滿足,安排!一個公司產品矩陣比較豐富的時候,用戶在不同系統之間來回切換,固然對

最近開發新產品,然后老板說我們現在系統太多了,每次切換系統登錄太麻煩了,能不能做個優化,同一賬號互通掉。作為一個資深架構獅,老板的要求肯定要滿足,安排!0a728資訊網——每日最新資訊28at.com

一個公司產品矩陣比較豐富的時候,用戶在不同系統之間來回切換,固然對產品用戶體驗上較差,并且增加用戶密碼管理成本。也沒有很好地利用內部流量進行用戶打通,并且每個產品的獨立體系會導致產品安全度下降。0a728資訊網——每日最新資訊28at.com

因此實現集團產品的單點登錄對用戶使用體驗以及效率提升有很大的幫助。那么如何實現統一認證呢?我們先了解一下傳統的身份驗證方式。0a728資訊網——每日最新資訊28at.com

1 傳統Session機制及身份認證方案

1.1 Cookie與服務器的交互

圖片圖片0a728資訊網——每日最新資訊28at.com

眾所周知,http是無狀態的協議,因此客戶每次通過瀏覽器訪問web頁面,請求到服務端時,服務器都會新建線程,打開新的會話,而且服務器也不會自動維護客戶的上下文信息。比如我們現在要實現一個電商內的購物車功能,要怎么才能知道哪些購物車請求對應的是來自同一個客戶的請求呢?0a728資訊網——每日最新資訊28at.com

圖片圖片0a728資訊網——每日最新資訊28at.com

因為 http 請求是無狀態請求,所以在 Web 領域,大部分都是通過這種方式解決。但是這么做有什么問題呢?我們接著看0a728資訊網——每日最新資訊28at.com

2 集群環境下的 Session 困境及解決方案

圖片圖片0a728資訊網——每日最新資訊28at.com

隨著技術的發展,用戶流量增大,單個服務器已經不能滿足系統的需要了,分布式架構開始流行。通常都會把系統部署在多臺服務器上,通過負載均衡把請求分發到其中的一臺服務器上,這樣很可能同一個用戶的請求被分發到不同的服務器上,因為 session 是保存在服務器上的,那么很有可能第一次請求訪問的 A 服務器,創建了 session,但是第二次訪問到了 B 服務器,這時就會出現取不到 session 的情況。0a728資訊網——每日最新資訊28at.com

我們知道,Session 一般是用來存會話全局的用戶信息(不僅僅是登陸方面的問題),用來簡化/加速后續的業務請求。0a728資訊網——每日最新資訊28at.com

傳統的 session 由服務器端生成并存儲,當應用進行分布式集群部署的時候,如何保證不同服務器上 session 信息能夠共享呢?0a728資訊網——每日最新資訊28at.com

2.1 Session共享方案

Session共享一般有兩種思路0a728資訊網——每日最新資訊28at.com

  • session復制
  • session集中存儲
2.1.1 session復制

session復制即將不同服務器上 session 數據進行復制,用戶登錄,修改,注銷時,將session信息同時也復制到其他機器上面去0a728資訊網——每日最新資訊28at.com

圖片圖片0a728資訊網——每日最新資訊28at.com

這種實現的問題就是實現成本高,維護難度大,并且會存在延遲登問題。0a728資訊網——每日最新資訊28at.com

2.1.2 session集中存儲

圖片圖片0a728資訊網——每日最新資訊28at.com

集中存儲就是將獲取session單獨放在一個服務中進行存儲,所有獲取session的統一來這個服務中去取。這樣就避免了同步和維護多套session的問題。一般我們都是使用redis進行集中式存儲session。0a728資訊網——每日最新資訊28at.com

3 多服務下的登陸困境及SSO方案

3.1 SSO的產生背景

圖片圖片0a728資訊網——每日最新資訊28at.com

如果企業做大了之后,一般都有很多的業務支持系統為其提供相應的管理和 IT 服務,按照傳統的驗證方式訪問多系統,每個單獨的系統都會有自己的安全體系和身份認證系統。進入每個系統都需要進行登錄,獲取session,再通過session訪問對應系統資源。0a728資訊網——每日最新資訊28at.com

這樣的局面不僅給管理上帶來了很大的困難,對客戶來說也極不友好,那么如何讓客戶只需登陸一次,就可以進入多個系統,而不需要重新登錄呢?0a728資訊網——每日最新資訊28at.com

圖片圖片0a728資訊網——每日最新資訊28at.com

“單點登錄”就是專為解決此類問題的。其大致思想流程如下:通過一個 ticket 進行串接各系統間的用戶信息0a728資訊網——每日最新資訊28at.com

3.2 SSO的底層原理 CAS

3.2.1 CAS實現單點登錄流程

我們知道對于完全不同域名的系統,cookie 是無法跨域名共享的,因此 sessionId 在頁面端也無法共享,因此需要實現單店登錄,就需要啟用一個專門用來登錄的域名如(ouath.com)來提供所有系統的sessionId。當業務系統被打開時,借助中心授權系統進行登錄,整體流程如下:0a728資訊網——每日最新資訊28at.com

  1. 當b.com打開時,發現自己未登陸,于是跳轉到ouath.com去登陸
  2. ouath.com登陸頁面被打開,用戶輸入帳戶/密碼登陸成功
  3. ouath.com登陸成功,種 cookie 到ouath.com域名下
  4. 把 sessionid 放入后臺redis,存放<ticket,sesssionid>數據結構,然后頁面重定向到A系統
  5. 當b.com重新被打開,發現仍然是未登陸,但是有了一個 ticket值
  6. 當b.com用ticket 值,到 redis 里查到 sessionid,并做 session 同步,然后種cookie給自己,頁面原地重定向
  7. 當b.com打開自己頁面,此時有了 cookie,后臺校驗登陸狀態,成功

整個交互流程圖如下:0a728資訊網——每日最新資訊28at.com

圖片圖片0a728資訊網——每日最新資訊28at.com

3.2.2 單點登錄流程演示

3.2.2.1 CAS登錄服務demo核心代碼0a728資訊網——每日最新資訊28at.com

  • 用戶實體類
public class UserForm implements Serializable{private static final long serialVersionUID = 1L;private String username;private String password;private String backurl;public String getUsername() {    return username;}public void setUsername(String username) {    this.username = username;}public String getPassword() {    return password;}public void setPassword(String password) {    this.password = password;}public String getBackurl() {    return backurl;}public void setBackurl(String backurl) {    this.backurl = backurl;}}
  • 登錄控制器
@Controllerpublic class IndexController {    @Autowired    private RedisTemplate redisTemplate;@GetMapping("/toLogin")public String toLogin(Model model,HttpServletRequest request) {    Object userInfo = request.getSession().getAttribute(LoginFilter.USER_INFO);    //不為空,則是已登陸狀態    if (null != userInfo){        String ticket = UUID.randomUUID().toString();        redisTemplate.opsForValue().set(ticket,userInfo,2, TimeUnit.SECONDS);        return "redirect:"+request.getParameter("url")+"?ticket="+ticket;    }    UserForm user = new UserForm();    user.setUsername("laowang");    user.setPassword("laowang");    user.setBackurl(request.getParameter("url"));    model.addAttribute("user", user);    return "login";}@PostMapping("/login")public void login(@ModelAttribute UserForm user,HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {    System.out.println("backurl:"+user.getBackurl());    request.getSession().setAttribute(LoginFilter.USER_INFO,user);    //登陸成功,創建用戶信息票據    String ticket = UUID.randomUUID().toString();    redisTemplate.opsForValue().set(ticket,user,20, TimeUnit.SECONDS);    //重定向,回原url  ---a.com    if (null == user.getBackurl() || user.getBackurl().length()==0){        response.sendRedirect("/index");    } else {        response.sendRedirect(user.getBackurl()+"?ticket="+ticket);    }}@GetMapping("/index")public ModelAndView index(HttpServletRequest request) {    ModelAndView modelAndView = new ModelAndView();    Object user = request.getSession().getAttribute(LoginFilter.USER_INFO);    UserForm userInfo = (UserForm) user;    modelAndView.setViewName("index");    modelAndView.addObject("user", userInfo);    request.getSession().setAttribute("test","123");    return modelAndView;}}
  • 登錄過濾器
public class LoginFilter implements Filter {    public static final String USER_INFO = "user";    @Override    public void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest,                     ServletResponse servletResponse, FilterChain filterChain)        throws IOException, ServletException {    HttpServletRequest request = (HttpServletRequest) servletRequest;     HttpServletResponse response = (HttpServletResponse)servletResponse;    Object userInfo = request.getSession().getAttribute(USER_INFO);;    //如果未登陸,則拒絕請求,轉向登陸頁面    String requestUrl = request.getServletPath();    if (!"/toLogin".equals(requestUrl)//不是登陸頁面            && !requestUrl.startsWith("/login")//不是去登陸            && null == userInfo) {//不是登陸狀態        request.getRequestDispatcher("/toLogin").forward(request,response);        return ;    }    filterChain.doFilter(request,servletResponse);}@Overridepublic void destroy() {}}
  • 配置過濾器
@Configurationpublic class LoginConfig {//配置filter生效@Beanpublic FilterRegistrationBean sessionFilterRegistration() {    FilterRegistrationBean registration = new FilterRegistrationBean();    registration.setFilter(new LoginFilter());    registration.addUrlPatterns("/*");    registration.addInitParameter("paramName", "paramValue");    registration.setName("sessionFilter");    registration.setOrder(1);    return registration;}}
  • 登錄頁面
<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head>    <title>enjoy login</title>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div text-align="center">    <h1>請登陸</h1>    <form action="#" th:action="@{/login}" th:object="${user}" method="post">        <p>用戶名: <input type="text" th:field="*{username}" /></p>        <p>密  碼: <input type="text" th:field="*{password}" /></p>        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>        <input type="text" th:field="*{backurl}" hidden="hidden" />    </form></div></body></html>

3.2.2.2 web系統demo核心代碼0a728資訊網——每日最新資訊28at.com

  • 過濾器
public class SSOFilter implements Filter {    private RedisTemplate redisTemplate;public static final String USER_INFO = "user";public SSOFilter(RedisTemplate redisTemplate){    this.redisTemplate = redisTemplate;}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest,                     ServletResponse servletResponse, FilterChain filterChain)        throws IOException, ServletException {    HttpServletRequest request = (HttpServletRequest) servletRequest;    HttpServletResponse response = (HttpServletResponse)servletResponse;    Object userInfo = request.getSession().getAttribute(USER_INFO);;    //如果未登陸,則拒絕請求,轉向登陸頁面    String requestUrl = request.getServletPath();    if (!"/toLogin".equals(requestUrl)//不是登陸頁面            && !requestUrl.startsWith("/login")//不是去登陸            && null == userInfo) {//不是登陸狀態        String ticket = request.getParameter("ticket");        //有票據,則使用票據去嘗試拿取用戶信息        if (null != ticket){            userInfo = redisTemplate.opsForValue().get(ticket);        }        //無法得到用戶信息,則去登陸頁面        if (null == userInfo){            response.sendRedirect("http://127.0.0.1:8080/toLogin?url="+request.getRequestURL().toString());            return ;        }        /**         * 將用戶信息,加載進session中         */        UserForm user = (UserForm) userInfo;        request.getSession().setAttribute(SSOFilter.USER_INFO,user);        redisTemplate.delete(ticket);    }    filterChain.doFilter(request,servletResponse);}@Overridepublic void destroy() {}}
  • 控制器
@Controllerpublic class IndexController {    @Autowired    private RedisTemplate redisTemplate;@GetMapping("/index")public ModelAndView index(HttpServletRequest request) {    ModelAndView modelAndView = new ModelAndView();    Object userInfo = request.getSession().getAttribute(SSOFilter.USER_INFO);    UserForm user = (UserForm) userInfo;    modelAndView.setViewName("index");    modelAndView.addObject("user", user);    request.getSession().setAttribute("test","123");    return modelAndView;}}
  • 首頁
<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head>    <title>enjoy index</title>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div th:object="${user}">    <h1>cas-website:歡迎你"></h1></div></body></html>

3.2.3 CAS的單點登錄和OAuth2的區別

OAuth2: 三方授權協議,允許用戶在不提供賬號密碼的情況下,通過信任的應用進行授權,使其客戶端可以訪問權限范圍內的資源。0a728資訊網——每日最新資訊28at.com

CAS: 中央認證服務(Central Authentication Service),一個基于Kerberos票據方式實現SSO單點登錄的框架,為Web 應用系統提供一種可靠的單點登錄解決方法(屬于 Web SSO )。0a728資訊網——每日最新資訊28at.com

  • CAS的單點登錄時保障客戶端的用戶資源的安全,OAuth2則是保障服務端的用戶資源的安全 。
  • CAS客戶端要獲取的最終信息是,這個用戶到底有沒有權限訪問我(CAS客戶端)的資源。OAuth2獲取的最終信息是,我(oauth2服務提供方)的用戶的資源到底能不能讓你(oauth2的客戶端)訪問。

因此,需要統一的賬號密碼進行身份認證,用CAS;需要授權第三方服務使用我方資源,使用OAuth2;0a728資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-112778-0.html告別繁瑣操作,實現一次登錄產品互通

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 定時任務數量爆炸?Netty教你如何應對百萬級挑戰

下一篇: PHP異步非阻塞MySQL客戶端連接池

標簽:
  • 熱門焦點
  • 一加Ace2 Pro官宣:普及16G內存 引領24G

    一加官方今天繼續為本月發布的新機一加Ace2 Pro帶來預熱,公布了內存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引領,還有呢?#一加Ace2Pro#,2023 年 8 月,敬請期待。”同時
  • 6月iOS設備性能榜:M2穩居榜首 A系列只能等一手3nm來救

    沒有新品發布,自然iOS設備性能榜的上榜設備就沒有什么更替,僅僅只有跑分變化而產生的排名變動,畢竟蘋果新品的發布節奏就是這樣的,一年下來也就幾個移動端新品,不會像安卓廠商,一
  • 0糖0卡0脂 旭日森林仙草烏龍茶優惠:15瓶到手29元

    旭日森林無糖仙草烏龍茶510ml*15瓶平時要賣為79.9元,今日下單領取50元優惠券,到手價為29.9元。產品規格:0糖0卡0脂,添加草本仙草汁,清涼爽口,富含茶多酚,保留
  • 多線程開發帶來的問題與解決方法

    使用多線程主要會帶來以下幾個問題:(一)線程安全問題  線程安全問題指的是在某一線程從開始訪問到結束訪問某一數據期間,該數據被其他的線程所修改,那么對于當前線程而言,該線程
  • 一文搞定Java NIO,以及各種奇葩流

    大家好,我是哪吒。很多朋友問我,如何才能學好IO流,對各種流的概念,云里霧里的,不求甚解。用到的時候,現百度,功能雖然實現了,但是為什么用這個?不知道。更別說效率問題了~下次再遇到,
  • 猿輔導與新東方的兩種“歸途”

    作者|卓心月 出品|零態LT(ID:LingTai_LT)如何成為一家偉大企業?答案一定是對&ldquo;勢&rdquo;的把握,這其中最關鍵的當屬對企業戰略的制定,且能夠站在未來看現在,即使這其中的
  • 小米公益基金會捐贈2500萬元馳援北京、河北暴雨救災

    8月2日消息,今日小米科技創始人雷軍在其微博上發布消息稱,小米公益基金會宣布捐贈2500萬元馳援北京、河北暴雨救災。攜手抗災,京冀安康!以下為公告原文
  • 疑似小米14外觀設計圖曝光:后置相機模組變化不大

    下半年的大幕已經開啟,而誰將成為下半年手機圈的主角就成為了大家關注的焦點,其中被傳有望拿下新一代驍龍8 Gen3旗艦芯片的小米14系列更是備受大家矚
  • 網傳小米汽車開始篩選交付中心 建筑面積不低于3000平方米

    7月7日消息,近日有微博網友@長三角行健者爆料稱,據經銷商集團反饋,小米汽車目前已經開始了交付中心的篩選工作,要求候選場地至少有120個車位,建筑不能低
Top 主站蜘蛛池模板: 石嘴山市| 六枝特区| 郸城县| 乡城县| 灵台县| 株洲市| 克什克腾旗| 四川省| 汝阳县| 额济纳旗| 松阳县| 拜城县| 永嘉县| 光泽县| 凌云县| 新宁县| 德令哈市| 富宁县| 宁德市| 上林县| 达州市| 灵川县| 宜阳县| 福安市| 拜泉县| 南开区| 贡山| 刚察县| 合水县| 习水县| 商水县| 庆云县| 内丘县| 门头沟区| 海城市| 普安县| 全南县| 西畴县| 海淀区| 姜堰市| 保山市|