前端登录,这一篇就够了

Posted 前端日志

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端登录,这一篇就够了相关的知识,希望对你有一定的参考价值。

HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。

为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。

Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。

有了 Cookie 之后,服务器端就能够获取到客户端传递过来的信息了,如果需要对信息进行验证,还需要通过 Session。

客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个便是 Session 对象。

有了 Cookie 和 Session 之后,我们就可以进行登录认证了。

页面时,会自动带上第一次登录时写入的 Cookie。
  • 服务器端比对 Cookie 中的 SessionId 和保存在服务器端的 SessionId 是否一致。
  • 如果一致,则身份验证成功。
  • 为了解决 Session + Cookie 机制暴露出的诸多问题,我们可以使用 Token 的登录方式。

    Token 是服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。

    时,带上第一次登录时获取的 Token。
  • 服务器端验证 Token ,有效则身份验证成功。
  • 编码的 header 部分、 .base64url 编码的 playload 部分,输出 unsignedToken。
  • 输入服务器端私钥、unsignedToken,输出 signature 签名。
  • 单点登录指的是在公司内部搭建一个公共的认证中心,公司下的所有产品的登录都可以在认证中心里完成,一个产品在认证中心登录后,再去访问另一个产品,可以不用再次登录,即可获取登录状态。

    下的 pageA 页面。
  • 由于没有登录,则会重定向到认证中心,并带上回调地址 www.sso.com?return_uri=a.com/pageA,以便登录后直接进入对应页面。
  • 用户在认证中心输入账号密码,提交登录。
  • 认证中心验证账号密码有效,然后重定向  a.com?ticket=123 带上授权码 ticket,并将认证中心 sso.com 的登录态写入 Cookie。
  • a.com 服务器中,拿着 ticket 向认证中心确认,授权码 ticket 真实有效。
  • 验证成功后,服务器将登录信息写入 Cookie(此时客户端有 2 个 Cookie 分别存有 a.comsso.com 的登录态)。

  • 认证中心登录完成之后,继续访问 a.com 下的其他页面:

    这个时候,由于 a.com 存在已登录的 Cookie 信息,所以服务器端直接认证成功。


    如果认证中心登录完成之后,访问 b.com 下的页面:

    这个时候,由于认证中心存在之前登录过的 Cookie,所以也不用再次输入账号密码,直接返回第 4 步,下发 ticket 给 b.com 即可。

    退出登录时:

    1. 清空 c.com 中的登录态 Cookie。
    2. 请求认证中心 sso.com 中的退出 api。
    3. 认证中心遍历下发过 ticket 的所有产品,并调用对应的退出 api,完成退出。

    在上文中,我们使用单点登录完成了多产品的登录态共享,但都是建立在一套统一的认证中心下,对于一些小型企业,未免太麻烦,有没有一种登录能够做到开箱即用?

    其实是有的,很多大厂都会提供自己的第三方登录服务,我们一起来分析一下。

    的运营者需要在微信开放平台注册账号,并向微信申请使用微信登录功能。
  • 申请成功后,得到申请的 appid、appsecret。
  • 用户在 a.com 上选择使用微信登录。
  • 这时会跳转微信的 OAuth 授权登录,并带上 a.com 的回调地址。
  • 用户输入微信账号和密码,登录成功后,需要选择具体的授权范围,如:授权用户的头像、昵称等。
  • 授权之后,微信会根据拉起 a.com?code=123 ,这时带上了一个临时票据 code。
  • 获取 code 之后, a.com 会拿着 code 、appid、appsecret,向微信服务器申请 token,验证成功后,微信会下发一个 token。
  • 有了 token 之后, a.com 就可以凭借 token 拿到对应的微信用户头像,用户昵称等信息了。
  • a.com 提示用户登录成功,并将登录状态写入 Cooke,以作为后续访问的凭证。
  • 本文介绍了 4 种常见的登录方式,原理应该大家都清楚了,总结一下这 4 种方案的使用场景:

  • Cookie + Session 历史悠久,适合于简单的后端架构,需开发人员自己处理好安全问题。
  • Token 方案对后端压力小,适合大型分布式的后端架构,但已分发出去的 token ,如果想收回权限,就不是很方便了。
  • SSO 单点登录,适用于中大型企业,想要统一内部所有产品的登录方式。
  • OAuth 第三方登录,简单易用,对用户和开发者都友好,但第三方平台很多,需要选择合适自己的第三方登录平台。

  • 单点登录(SSO)看这一篇就够了

    背景

    在企业发展初期,企业使用的系统很少,通常一个或者两个,每个系统都有自己的登录模块,运营人员每天用自己的账号登录,很方便。

    但随着企业的发展,用到的系统随之增多,运营人员在操作不同的系统时,需要多次登录,而且每个系统的账号都不一样,这对于运营人员

    来说,很不方便。于是,就想到是不是可以在一个系统登录,其他系统就不用登录了呢?这就是单点登录要解决的问题。

    单点登录英文全称Single Sign On,简称就是SSO。它的解释是:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

     
    技术图片
    image

    如图所示,图中有4个系统,分别是Application1、Application2、Application3、和SSO。Application1、Application2、Application3没有登录模块,而SSO只有登录模块,没有其他的业务模块,当Application1、Application2、Application3需要登录时,将跳到SSO系统,SSO系统完成登录,其他的应用系统也就随之登录了。这完全符合我们对单点登录(SSO)的定义。

    技术实现

    在说单点登录(SSO)的技术实现之前,我们先说一说普通的登录认证机制。

     
    技术图片
    image

    如上图所示,我们在浏览器(Browser)中访问一个应用,这个应用需要登录,我们填写完用户名和密码后,完成登录认证。这时,我们在这个用户的session中标记登录状态为yes(已登录),同时在浏览器(Browser)中写入Cookie,这个Cookie是这个用户的唯一标识。下次我们再访问这个应用的时候,请求中会带上这个Cookie,服务端会根据这个Cookie找到对应的session,通过session来判断这个用户是否登录。如果不做特殊配置,这个Cookie的名字叫做jsessionid,值在服务端(server)是唯一的。

    同域下的单点登录

    一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:a.com,同时有两个业务系统分别为:app1.a.com和app2.a.com。我们要做单点登录(SSO),需要一个登录系统,叫做:sso.a.com。

    我们只要在sso.a.com登录,app1.a.com和app2.a.com就也登录了。通过上面的登陆认证机制,我们可以知道,在sso.a.com中登录了,其实是在sso.a.com的服务端的session中记录了登录状态,同时在浏览器端(Browser)的sso.a.com下写入了Cookie。那么我们怎么才能让app1.a.com和app2.a.com登录呢?这里有两个问题:

    • Cookie是不能跨域的,我们Cookie的domain属性是sso.a.com,在给app1.a.com和app2.a.com发送请求是带不上的。
    • sso、app1和app2是不同的应用,它们的session存在自己的应用内,是不共享的。
     
    技术图片
    image

    那么我们如何解决这两个问题呢?针对第一个问题,sso登录以后,可以将Cookie的域设置为顶域,即.a.com,这样所有子域的系统都可以访问到顶域的Cookie。我们在设置Cookie时,只能设置顶域和自己的域,不能设置其他的域。比如:我们不能在自己的系统中给baidu.com的域设置Cookie。

    Cookie的问题解决了,我们再来看看session的问题。我们在sso系统登录了,这时再访问app1,Cookie也带到了app1的服务端(Server),app1的服务端怎么找到这个Cookie对应的Session呢?这里就要把3个系统的Session共享,如图所示。共享Session的解决方案有很多,例如:Spring-Session。这样第2个问题也解决了。

    同域下的单点登录就实现了,但这还不是真正的单点登录。

    不同域下的单点登录

    同域下的单点登录是巧用了Cookie顶域的特性。如果是不同域呢?不同域之间Cookie是不共享的,怎么办?

    这里我们就要说一说CAS流程了,这个流程是单点登录的标准流程。

     
    技术图片
    cas_flow_diagram

    上图是CAS官网上的标准流程,具体流程如下:

    1. 用户访问app系统,app系统是需要登录的,但用户现在没有登录。
    2. 跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
    3. 用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
    4. SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
    5. app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
    6. 验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

    至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

    1. 用户访问app2系统,app2系统没有登录,跳转到SSO。
    2. 由于SSO已经登录了,不需要重新登录认证。
    3. SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
    4. app2拿到ST,后台访问SSO,验证ST是否有效。
    5. 验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

    这样,app2系统不需要走登录流程,就已经是登录了。SSO,app和app2在不同的域,它们之间的session不共享也是没问题的。

    有的同学问我,SSO系统登录后,跳回原业务系统时,带了个参数ST,业务系统还要拿ST再次访问SSO进行验证,觉得这个步骤有点多余。他想SSO登录认证通过后,通过回调地址将用户信息返回给原业务系统,原业务系统直接设置登录状态,这样流程简单,也完成了登录,不是很好吗?

    其实这样问题时很严重的,如果我在SSO没有登录,而是直接在浏览器中敲入回调的地址,并带上伪造的用户信息,是不是业务系统也认为登录了呢?这是很可怕的。

    总结

    单点登录(SSO)的所有流程都介绍完了,原理大家都清楚了。总结一下单点登录要做的事情:

    • 单点登录(SSO系统)是保障各业务系统的用户资源的安全 。
    • 各个业务系统获得的信息是,这个用户能不能访问我的资源。
    • 单点登录,资源都在各个业务系统这边,不在SSO那一方。 用户在给SSO服务器提供了用户名密码后,作为业务系统并不知道这件事。 SSO随便给业务系统一个ST,那么业务系统是不能确定这个ST是用户伪造的,还是真的有效,所以要拿着这个ST去SSO服务器再问一下,这个用户给我的ST是否有效,是有效的我才能让这个用户访问。



    以上是关于前端登录,这一篇就够了的主要内容,如果未能解决你的问题,请参考以下文章

    Flutter入门这一篇效率文章就够了

    单点登录看这一篇就够了

    单点登录(SSO)看这一篇就够了

    前端开发框架工具汇总,看这一篇就够了!

    CAS单点登录,这一篇就够了!

    关于接口测试看这一篇就够了

    (c)2006-2024 SYSTEM All Rights Reserved IT常识