本文目录导读:
单点登录前端实现方案
单点登录概述
单点登录(Single Sign - On,SSO)是一种身份验证机制,它允许用户使用一组凭据(如用户名和密码)登录到多个相关但独立的应用程序或系统中,在现代企业级应用和互联网应用场景中,单点登录具有诸多优势,例如提升用户体验,用户无需在每个应用中重复输入登录信息;提高安全性,通过集中式的身份管理便于实施安全策略;降低管理成本,减少了用户账号管理的复杂性等。
前端实现单点登录的关键技术点
(一)跨域处理
图片来源于网络,如有侵权联系删除
1、JSONP(JSON with Padding)
- JSONP是一种跨域数据交互的方法,在单点登录场景中,当不同的子应用处于不同的域名下时,主登录应用(提供单点登录功能的应用)可能需要向子应用传递登录状态信息,JSONP利用<script>
标签不受同源策略限制的特性来实现跨域数据获取。
- 主登录应用可以定义一个回调函数,如function handleLoginData(data) {... }
,然后通过在子应用中动态创建一个<script>
标签,其src
属性指向主登录应用的一个接口,如https://main - login - app.com/api/getLoginData?callback = handleLoginData
,主登录应用在接收到请求后,会将登录数据包装在回调函数中返回,例如handleLoginData({username: 'user1', isLoggedIn: true})
,这样就实现了跨域的数据传递。
- JSONP也有局限性,它只能进行GET请求,并且存在一定的安全风险,因为它信任服务端返回的JavaScript代码,容易受到XSS(跨站脚本攻击)攻击。
2、CORS(Cross - Origin Resource Sharing)
- CORS是一种更为现代和安全的跨域解决方案,在前端,浏览器会自动在跨域请求中添加Origin
头信息,标识请求的来源,服务器端需要配置允许的源(Access - Control - Allow - Origin
)等相关CORS头信息。
- 对于单点登录,如果主登录应用和子应用的服务器都正确配置了CORS,前端可以使用常规的fetch
或XMLHttpRequest
进行跨域的登录状态验证和数据获取,在前端使用fetch('https://sub - app.com/api/checkLoginStatus', {credentials: 'include'})
来检查子应用的登录状态,其中credentials: 'include'
会在请求中包含 cookies等凭证信息,以便进行有效的登录状态验证。
(二)登录状态管理
1、Cookie
- Cookie是一种常见的在浏览器端存储用户登录状态的方式,在单点登录中,主登录应用在用户成功登录后,可以在响应中设置一个加密的Cookie,例如Set - Cookie: sso_token=encrypted_token; path=/; domain=.example.com
,这里的domain
属性可以设置为顶级域名,使得该Cookie可以被同域名下的多个子应用共享。
- 子应用在接收到请求时,可以通过读取Cookie
中的sso_token
来验证用户的登录状态,Cookie也存在一些安全问题,如容易受到CSRF(跨站请求伪造)攻击,需要采取额外的防范措施,如使用CSRF令牌等。
2、LocalStorage和SessionStorage
- LocalStorage和SessionStorage是HTML5 Web Storage API提供的在浏览器端存储数据的方式,与Cookie不同,它们存储的数据不会自动随每个请求发送到服务器端。
- 在单点登录前端实现中,可以将登录相关的一些辅助信息,如用户的基本信息缓存到LocalStorage或SessionStorage中,在主登录应用登录成功后,除了设置Cookie,还可以将用户的头像、昵称等信息存储到LocalStorage中,如localStorage.setItem('user_avatar', 'https://example.com/avatar.jpg')
,子应用可以读取这些信息来提供更个性化的用户界面,同时可以根据LocalStorage中的登录相关标志(如isLoggedIn
)来判断用户是否已登录,避免频繁向服务器验证登录状态,提高应用的性能。
前端单点登录的流程实现
(一)初始登录
1、用户访问主登录应用
图片来源于网络,如有侵权联系删除
- 用户首先访问主登录应用的登录页面,前端页面通常会包含用户名和密码输入框、登录按钮等元素,使用HTML和CSS可以构建出美观且易用的登录界面。
```html
<form id="loginForm">
<input type="text" id="username" placeholder="Username" />
<input type="password" id="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
```
- 当用户点击登录按钮时,前端会使用JavaScript来收集用户名和密码信息,并通过fetch
或XMLHttpRequest
将数据发送到主登录应用的登录接口,如https://main - login - app.com/api/login
。
2、主登录应用验证并设置登录状态
- 主登录应用的服务器端接收到登录请求后,会验证用户名和密码的正确性,如果验证成功,会生成一个登录令牌(如JWT - JSON Web Token),并在响应中设置Cookie来表示用户已登录,将登录成功的相关信息(如用户信息、权限信息等)返回给前端。
- 前端接收到登录成功的响应后,除了存储返回的信息到LocalStorage等地方,还可以根据业务需求进行页面跳转,例如跳转到用户的仪表盘页面或者是重定向到其他相关的子应用。
(二)访问子应用
1、子应用检测登录状态
- 当用户访问子应用时,子应用的前端会首先检测登录状态,如果子应用使用Cookie来验证登录状态,它会检查是否存在有效的登录Cookie,如果使用LocalStorage中的标志位,会读取isLoggedIn
等相关标志。
- 如果登录状态未检测到,子应用的前端可以引导用户跳转到主登录应用进行登录,或者显示一个登录提示框引导用户登录,可以使用window.location.href = 'https://main - login - app.com/login'
来进行页面跳转。
图片来源于网络,如有侵权联系删除
2、子应用与主登录应用交互(可选)
- 在一些复杂的单点登录场景中,子应用可能需要进一步与主登录应用交互来获取更详细的登录信息,这可以通过前面提到的跨域技术(如CORS或JSONP)来实现,子应用可以发送一个请求到主登录应用的/api/getUserDetails
接口来获取用户的详细信息,如用户的角色、所属部门等,以便在子应用中进行权限控制和个性化展示。
安全考虑
1、防范XSS攻击
- 在使用JSONP等跨域技术时,要特别注意防范XSS攻击,对于从外部来源(尤其是不可信来源)获取的数据,要进行严格的过滤和转义,在将从主登录应用获取的用户信息显示在子应用的页面上时,如果该信息包含HTML标签,需要使用合适的库(如DOMPurify
)来净化数据,防止恶意脚本注入。
2、CSRF防范
- 由于Cookie在单点登录中广泛用于存储登录状态,容易受到CSRF攻击,子应用可以采用多种方式防范CSRF,如在每个表单中添加隐藏的CSRF令牌,当用户提交表单时,服务器会验证令牌的有效性,在使用fetch
或XMLHttpRequest
进行跨域请求时,要确保请求的来源是合法的,例如通过验证Referer
头信息(虽然Referer
头信息可以被伪造,但在一定程度上可以增加安全性)。
3、令牌安全
- 如果使用JWT等令牌来表示登录状态,要确保令牌的保密性和完整性,在前端存储令牌时,要避免将其暴露在不安全的环境中,如避免在全局变量中明文存储,要定期更新令牌,防止令牌被窃取后长期有效被恶意利用。
性能优化
1、减少不必要的登录状态验证
- 在子应用中,可以根据业务逻辑合理安排登录状态验证的频率,如果用户在短时间内多次访问子应用的不同页面,不必每次都向主登录应用或服务器验证登录状态,可以依赖LocalStorage或SessionStorage中的缓存信息,只有当缓存信息过期或者存在可疑操作时,才进行重新验证。
2、优化跨域请求
- 对于跨域请求,要尽量减少请求的大小和频率,在使用CORS进行跨域的登录状态验证时,可以通过设置合适的缓存头信息(如Cache - Control
)来减少不必要的重复请求,对于批量的登录相关数据获取,可以采用异步请求的方式,避免阻塞页面的渲染,提高用户体验。
单点登录前端实现需要综合考虑跨域处理、登录状态管理、流程实现、安全和性能等多方面的因素,通过合理运用相关技术和优化措施,可以构建出高效、安全且用户体验良好的单点登录前端解决方案。
评论列表